kailash 0.8.3__py3-none-any.whl → 0.8.5__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.
Files changed (84) hide show
  1. kailash/__init__.py +1 -7
  2. kailash/cli/__init__.py +11 -1
  3. kailash/cli/validation_audit.py +570 -0
  4. kailash/core/actors/supervisor.py +1 -1
  5. kailash/core/resilience/circuit_breaker.py +71 -1
  6. kailash/core/resilience/health_monitor.py +172 -0
  7. kailash/edge/compliance.py +33 -0
  8. kailash/edge/consistency.py +609 -0
  9. kailash/edge/coordination/__init__.py +30 -0
  10. kailash/edge/coordination/global_ordering.py +355 -0
  11. kailash/edge/coordination/leader_election.py +217 -0
  12. kailash/edge/coordination/partition_detector.py +296 -0
  13. kailash/edge/coordination/raft.py +485 -0
  14. kailash/edge/discovery.py +63 -1
  15. kailash/edge/migration/__init__.py +19 -0
  16. kailash/edge/migration/edge_migrator.py +832 -0
  17. kailash/edge/monitoring/__init__.py +21 -0
  18. kailash/edge/monitoring/edge_monitor.py +736 -0
  19. kailash/edge/prediction/__init__.py +10 -0
  20. kailash/edge/prediction/predictive_warmer.py +591 -0
  21. kailash/edge/resource/__init__.py +102 -0
  22. kailash/edge/resource/cloud_integration.py +796 -0
  23. kailash/edge/resource/cost_optimizer.py +949 -0
  24. kailash/edge/resource/docker_integration.py +919 -0
  25. kailash/edge/resource/kubernetes_integration.py +893 -0
  26. kailash/edge/resource/platform_integration.py +913 -0
  27. kailash/edge/resource/predictive_scaler.py +959 -0
  28. kailash/edge/resource/resource_analyzer.py +824 -0
  29. kailash/edge/resource/resource_pools.py +610 -0
  30. kailash/integrations/dataflow_edge.py +261 -0
  31. kailash/mcp_server/registry_integration.py +1 -1
  32. kailash/monitoring/__init__.py +18 -0
  33. kailash/monitoring/alerts.py +646 -0
  34. kailash/monitoring/metrics.py +677 -0
  35. kailash/nodes/__init__.py +2 -0
  36. kailash/nodes/ai/__init__.py +17 -0
  37. kailash/nodes/ai/a2a.py +1914 -43
  38. kailash/nodes/ai/a2a_backup.py +1807 -0
  39. kailash/nodes/ai/hybrid_search.py +972 -0
  40. kailash/nodes/ai/semantic_memory.py +558 -0
  41. kailash/nodes/ai/streaming_analytics.py +947 -0
  42. kailash/nodes/base.py +545 -0
  43. kailash/nodes/edge/__init__.py +36 -0
  44. kailash/nodes/edge/base.py +240 -0
  45. kailash/nodes/edge/cloud_node.py +710 -0
  46. kailash/nodes/edge/coordination.py +239 -0
  47. kailash/nodes/edge/docker_node.py +825 -0
  48. kailash/nodes/edge/edge_data.py +582 -0
  49. kailash/nodes/edge/edge_migration_node.py +392 -0
  50. kailash/nodes/edge/edge_monitoring_node.py +421 -0
  51. kailash/nodes/edge/edge_state.py +673 -0
  52. kailash/nodes/edge/edge_warming_node.py +393 -0
  53. kailash/nodes/edge/kubernetes_node.py +652 -0
  54. kailash/nodes/edge/platform_node.py +766 -0
  55. kailash/nodes/edge/resource_analyzer_node.py +378 -0
  56. kailash/nodes/edge/resource_optimizer_node.py +501 -0
  57. kailash/nodes/edge/resource_scaler_node.py +397 -0
  58. kailash/nodes/ports.py +676 -0
  59. kailash/runtime/local.py +344 -1
  60. kailash/runtime/validation/__init__.py +20 -0
  61. kailash/runtime/validation/connection_context.py +119 -0
  62. kailash/runtime/validation/enhanced_error_formatter.py +202 -0
  63. kailash/runtime/validation/error_categorizer.py +164 -0
  64. kailash/runtime/validation/metrics.py +380 -0
  65. kailash/runtime/validation/performance.py +615 -0
  66. kailash/runtime/validation/suggestion_engine.py +212 -0
  67. kailash/testing/fixtures.py +2 -2
  68. kailash/workflow/builder.py +234 -8
  69. kailash/workflow/contracts.py +418 -0
  70. kailash/workflow/edge_infrastructure.py +369 -0
  71. kailash/workflow/migration.py +3 -3
  72. kailash/workflow/type_inference.py +669 -0
  73. {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/METADATA +44 -27
  74. {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/RECORD +78 -28
  75. kailash/nexus/__init__.py +0 -21
  76. kailash/nexus/cli/__init__.py +0 -5
  77. kailash/nexus/cli/__main__.py +0 -6
  78. kailash/nexus/cli/main.py +0 -176
  79. kailash/nexus/factory.py +0 -413
  80. kailash/nexus/gateway.py +0 -545
  81. {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/WHEEL +0 -0
  82. {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/entry_points.txt +0 -0
  83. {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/licenses/LICENSE +0 -0
  84. {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,825 @@
1
+ """Docker integration node for edge resource management."""
2
+
3
+ from typing import Any, Dict, List, Optional
4
+
5
+ from kailash.edge.resource.docker_integration import (
6
+ ContainerSpec,
7
+ ContainerState,
8
+ DockerIntegration,
9
+ NetworkMode,
10
+ RestartPolicyType,
11
+ ServiceSpec,
12
+ )
13
+ from kailash.nodes.base import NodeParameter, register_node
14
+ from kailash.nodes.base_async import AsyncNode
15
+
16
+
17
+ @register_node()
18
+ class DockerNode(AsyncNode):
19
+ """Node for Docker container and service management."""
20
+
21
+ def __init__(self, **kwargs):
22
+ super().__init__(**kwargs)
23
+ self.docker_integration: Optional[DockerIntegration] = None
24
+
25
+ @property
26
+ def input_parameters(self) -> Dict[str, NodeParameter]:
27
+ """Define input parameters."""
28
+ return {
29
+ "operation": NodeParameter(
30
+ name="operation",
31
+ type=str,
32
+ required=True,
33
+ description="Operation to perform",
34
+ enum=[
35
+ "initialize",
36
+ "create_container",
37
+ "start_container",
38
+ "stop_container",
39
+ "remove_container",
40
+ "get_container_status",
41
+ "list_containers",
42
+ "create_service",
43
+ "update_service",
44
+ "scale_service",
45
+ "get_service_status",
46
+ "collect_metrics",
47
+ "get_system_info",
48
+ "start_monitoring",
49
+ "stop_monitoring",
50
+ ],
51
+ ),
52
+ "docker_host": NodeParameter(
53
+ name="docker_host",
54
+ type=str,
55
+ required=False,
56
+ description="Docker daemon socket URL",
57
+ ),
58
+ "api_version": NodeParameter(
59
+ name="api_version",
60
+ type=str,
61
+ required=False,
62
+ description="Docker API version",
63
+ ),
64
+ "timeout": NodeParameter(
65
+ name="timeout",
66
+ type=int,
67
+ required=False,
68
+ description="API timeout in seconds",
69
+ ),
70
+ # Container operations
71
+ "container_name": NodeParameter(
72
+ name="container_name",
73
+ type=str,
74
+ required=False,
75
+ description="Container name",
76
+ ),
77
+ "container_id": NodeParameter(
78
+ name="container_id",
79
+ type=str,
80
+ required=False,
81
+ description="Container ID",
82
+ ),
83
+ "image": NodeParameter(
84
+ name="image", type=str, required=False, description="Docker image"
85
+ ),
86
+ "command": NodeParameter(
87
+ name="command",
88
+ type=list,
89
+ required=False,
90
+ description="Container command",
91
+ ),
92
+ "environment": NodeParameter(
93
+ name="environment",
94
+ type=dict,
95
+ required=False,
96
+ description="Environment variables",
97
+ ),
98
+ "ports": NodeParameter(
99
+ name="ports",
100
+ type=dict,
101
+ required=False,
102
+ description="Port mappings (container_port -> host_port)",
103
+ ),
104
+ "volumes": NodeParameter(
105
+ name="volumes",
106
+ type=dict,
107
+ required=False,
108
+ description="Volume mappings (host_path -> container_path)",
109
+ ),
110
+ "restart_policy": NodeParameter(
111
+ name="restart_policy",
112
+ type=str,
113
+ required=False,
114
+ description="Container restart policy",
115
+ enum=["no", "always", "unless-stopped", "on-failure"],
116
+ ),
117
+ "memory_limit": NodeParameter(
118
+ name="memory_limit",
119
+ type=str,
120
+ required=False,
121
+ description="Memory limit (e.g., '512m', '1g')",
122
+ ),
123
+ "cpu_limit": NodeParameter(
124
+ name="cpu_limit",
125
+ type=float,
126
+ required=False,
127
+ description="CPU limit in cores",
128
+ ),
129
+ "network_mode": NodeParameter(
130
+ name="network_mode",
131
+ type=str,
132
+ required=False,
133
+ description="Network mode",
134
+ enum=["bridge", "host", "none", "container", "custom"],
135
+ ),
136
+ "labels": NodeParameter(
137
+ name="labels", type=dict, required=False, description="Container labels"
138
+ ),
139
+ "edge_node": NodeParameter(
140
+ name="edge_node",
141
+ type=str,
142
+ required=False,
143
+ description="Target edge node for container placement",
144
+ ),
145
+ "healthcheck": NodeParameter(
146
+ name="healthcheck",
147
+ type=dict,
148
+ required=False,
149
+ description="Container health check configuration",
150
+ ),
151
+ # Service operations (Docker Swarm)
152
+ "service_name": NodeParameter(
153
+ name="service_name",
154
+ type=str,
155
+ required=False,
156
+ description="Service name",
157
+ ),
158
+ "service_id": NodeParameter(
159
+ name="service_id", type=str, required=False, description="Service ID"
160
+ ),
161
+ "replicas": NodeParameter(
162
+ name="replicas",
163
+ type=int,
164
+ required=False,
165
+ description="Number of service replicas",
166
+ ),
167
+ "constraints": NodeParameter(
168
+ name="constraints",
169
+ type=list,
170
+ required=False,
171
+ description="Service placement constraints",
172
+ ),
173
+ "placement_preferences": NodeParameter(
174
+ name="placement_preferences",
175
+ type=list,
176
+ required=False,
177
+ description="Service placement preferences",
178
+ ),
179
+ "update_config": NodeParameter(
180
+ name="update_config",
181
+ type=dict,
182
+ required=False,
183
+ description="Service update configuration",
184
+ ),
185
+ "rollback_config": NodeParameter(
186
+ name="rollback_config",
187
+ type=dict,
188
+ required=False,
189
+ description="Service rollback configuration",
190
+ ),
191
+ # List operations
192
+ "all_containers": NodeParameter(
193
+ name="all_containers",
194
+ type=bool,
195
+ required=False,
196
+ description="Include stopped containers in list",
197
+ ),
198
+ "filters": NodeParameter(
199
+ name="filters",
200
+ type=dict,
201
+ required=False,
202
+ description="Container filters",
203
+ ),
204
+ # Control operations
205
+ "force": NodeParameter(
206
+ name="force", type=bool, required=False, description="Force operation"
207
+ ),
208
+ "stop_timeout": NodeParameter(
209
+ name="stop_timeout",
210
+ type=int,
211
+ required=False,
212
+ description="Container stop timeout in seconds",
213
+ ),
214
+ }
215
+
216
+ @property
217
+ def output_parameters(self) -> Dict[str, NodeParameter]:
218
+ """Define output parameters."""
219
+ return {
220
+ "status": NodeParameter(
221
+ name="status", type=str, description="Operation status"
222
+ ),
223
+ "result": NodeParameter(
224
+ name="result", type=dict, description="Operation result"
225
+ ),
226
+ "containers": NodeParameter(
227
+ name="containers", type=list, description="List of containers"
228
+ ),
229
+ "services": NodeParameter(
230
+ name="services", type=list, description="List of services"
231
+ ),
232
+ "metrics": NodeParameter(
233
+ name="metrics", type=dict, description="Container metrics"
234
+ ),
235
+ "system_info": NodeParameter(
236
+ name="system_info", type=dict, description="Docker system information"
237
+ ),
238
+ "container_created": NodeParameter(
239
+ name="container_created",
240
+ type=bool,
241
+ description="Whether container was created",
242
+ ),
243
+ "container_started": NodeParameter(
244
+ name="container_started",
245
+ type=bool,
246
+ description="Whether container was started",
247
+ ),
248
+ "container_stopped": NodeParameter(
249
+ name="container_stopped",
250
+ type=bool,
251
+ description="Whether container was stopped",
252
+ ),
253
+ "container_removed": NodeParameter(
254
+ name="container_removed",
255
+ type=bool,
256
+ description="Whether container was removed",
257
+ ),
258
+ "service_created": NodeParameter(
259
+ name="service_created",
260
+ type=bool,
261
+ description="Whether service was created",
262
+ ),
263
+ "service_updated": NodeParameter(
264
+ name="service_updated",
265
+ type=bool,
266
+ description="Whether service was updated",
267
+ ),
268
+ "service_scaled": NodeParameter(
269
+ name="service_scaled",
270
+ type=bool,
271
+ description="Whether service was scaled",
272
+ ),
273
+ "monitoring_started": NodeParameter(
274
+ name="monitoring_started",
275
+ type=bool,
276
+ description="Whether monitoring was started",
277
+ ),
278
+ "monitoring_stopped": NodeParameter(
279
+ name="monitoring_stopped",
280
+ type=bool,
281
+ description="Whether monitoring was stopped",
282
+ ),
283
+ }
284
+
285
+ def get_parameters(self) -> Dict[str, NodeParameter]:
286
+ """Get all parameters for this node."""
287
+ return self.input_parameters
288
+
289
+ async def async_run(self, **kwargs) -> Dict[str, Any]:
290
+ """Execute Docker operation.
291
+
292
+ Args:
293
+ **kwargs: Operation parameters
294
+
295
+ Returns:
296
+ Operation result
297
+ """
298
+ operation = kwargs.get("operation")
299
+
300
+ if not operation:
301
+ return {"status": "error", "error": "Operation is required"}
302
+
303
+ try:
304
+ if operation == "initialize":
305
+ return await self._initialize_docker(**kwargs)
306
+ elif operation == "create_container":
307
+ return await self._create_container(**kwargs)
308
+ elif operation == "start_container":
309
+ return await self._start_container(**kwargs)
310
+ elif operation == "stop_container":
311
+ return await self._stop_container(**kwargs)
312
+ elif operation == "remove_container":
313
+ return await self._remove_container(**kwargs)
314
+ elif operation == "get_container_status":
315
+ return await self._get_container_status(**kwargs)
316
+ elif operation == "list_containers":
317
+ return await self._list_containers(**kwargs)
318
+ elif operation == "create_service":
319
+ return await self._create_service(**kwargs)
320
+ elif operation == "update_service":
321
+ return await self._update_service(**kwargs)
322
+ elif operation == "scale_service":
323
+ return await self._scale_service(**kwargs)
324
+ elif operation == "get_service_status":
325
+ return await self._get_service_status(**kwargs)
326
+ elif operation == "collect_metrics":
327
+ return await self._collect_metrics(**kwargs)
328
+ elif operation == "get_system_info":
329
+ return await self._get_system_info(**kwargs)
330
+ elif operation == "start_monitoring":
331
+ return await self._start_monitoring(**kwargs)
332
+ elif operation == "stop_monitoring":
333
+ return await self._stop_monitoring(**kwargs)
334
+ else:
335
+ return {"status": "error", "error": f"Unknown operation: {operation}"}
336
+
337
+ except Exception as e:
338
+ return {"status": "error", "error": f"Docker operation failed: {str(e)}"}
339
+
340
+ async def _initialize_docker(self, **kwargs) -> Dict[str, Any]:
341
+ """Initialize Docker integration."""
342
+ docker_host = kwargs.get("docker_host")
343
+ api_version = kwargs.get("api_version", "auto")
344
+ timeout = kwargs.get("timeout", 60)
345
+
346
+ try:
347
+ self.docker_integration = DockerIntegration(
348
+ docker_host=docker_host, api_version=api_version, timeout=timeout
349
+ )
350
+
351
+ await self.docker_integration.initialize()
352
+
353
+ return {
354
+ "status": "success",
355
+ "docker_initialized": True,
356
+ "result": {
357
+ "message": "Docker integration initialized successfully",
358
+ "docker_host": docker_host,
359
+ "api_version": api_version,
360
+ "swarm_enabled": self.docker_integration.swarm_enabled,
361
+ },
362
+ }
363
+
364
+ except Exception as e:
365
+ return {
366
+ "status": "error",
367
+ "docker_initialized": False,
368
+ "error": f"Failed to initialize Docker: {str(e)}",
369
+ }
370
+
371
+ async def _create_container(self, **kwargs) -> Dict[str, Any]:
372
+ """Create Docker container."""
373
+ if not self.docker_integration:
374
+ await self._initialize_docker(**kwargs)
375
+
376
+ container_name = kwargs.get("container_name")
377
+ image = kwargs.get("image")
378
+
379
+ if not container_name or not image:
380
+ return {
381
+ "status": "error",
382
+ "container_created": False,
383
+ "error": "container_name and image are required",
384
+ }
385
+
386
+ try:
387
+ # Create container specification
388
+ container_spec = ContainerSpec(
389
+ name=container_name,
390
+ image=image,
391
+ command=kwargs.get("command"),
392
+ environment=kwargs.get("environment", {}),
393
+ ports=kwargs.get("ports", {}),
394
+ volumes=kwargs.get("volumes", {}),
395
+ restart_policy=RestartPolicyType(
396
+ kwargs.get("restart_policy", "unless-stopped")
397
+ ),
398
+ memory_limit=kwargs.get("memory_limit"),
399
+ cpu_limit=kwargs.get("cpu_limit"),
400
+ network_mode=NetworkMode(kwargs.get("network_mode", "bridge")),
401
+ labels=kwargs.get("labels", {}),
402
+ edge_node=kwargs.get("edge_node"),
403
+ healthcheck=kwargs.get("healthcheck"),
404
+ )
405
+
406
+ # Create container
407
+ result = await self.docker_integration.create_container(container_spec)
408
+
409
+ return {
410
+ "status": result.get("status", "unknown"),
411
+ "container_created": result.get("status") == "created",
412
+ "result": result,
413
+ }
414
+
415
+ except Exception as e:
416
+ return {
417
+ "status": "error",
418
+ "container_created": False,
419
+ "error": f"Failed to create container: {str(e)}",
420
+ }
421
+
422
+ async def _start_container(self, **kwargs) -> Dict[str, Any]:
423
+ """Start Docker container."""
424
+ if not self.docker_integration:
425
+ await self._initialize_docker(**kwargs)
426
+
427
+ container_id = kwargs.get("container_id") or kwargs.get("container_name")
428
+
429
+ if not container_id:
430
+ return {
431
+ "status": "error",
432
+ "container_started": False,
433
+ "error": "container_id or container_name is required",
434
+ }
435
+
436
+ try:
437
+ result = await self.docker_integration.start_container(container_id)
438
+
439
+ return {
440
+ "status": result.get("status", "unknown"),
441
+ "container_started": result.get("status") == "started",
442
+ "result": result,
443
+ }
444
+
445
+ except Exception as e:
446
+ return {
447
+ "status": "error",
448
+ "container_started": False,
449
+ "error": f"Failed to start container: {str(e)}",
450
+ }
451
+
452
+ async def _stop_container(self, **kwargs) -> Dict[str, Any]:
453
+ """Stop Docker container."""
454
+ if not self.docker_integration:
455
+ await self._initialize_docker(**kwargs)
456
+
457
+ container_id = kwargs.get("container_id") or kwargs.get("container_name")
458
+ stop_timeout = kwargs.get("stop_timeout", 10)
459
+
460
+ if not container_id:
461
+ return {
462
+ "status": "error",
463
+ "container_stopped": False,
464
+ "error": "container_id or container_name is required",
465
+ }
466
+
467
+ try:
468
+ result = await self.docker_integration.stop_container(
469
+ container_id, stop_timeout
470
+ )
471
+
472
+ return {
473
+ "status": result.get("status", "unknown"),
474
+ "container_stopped": result.get("status") == "stopped",
475
+ "result": result,
476
+ }
477
+
478
+ except Exception as e:
479
+ return {
480
+ "status": "error",
481
+ "container_stopped": False,
482
+ "error": f"Failed to stop container: {str(e)}",
483
+ }
484
+
485
+ async def _remove_container(self, **kwargs) -> Dict[str, Any]:
486
+ """Remove Docker container."""
487
+ if not self.docker_integration:
488
+ await self._initialize_docker(**kwargs)
489
+
490
+ container_id = kwargs.get("container_id") or kwargs.get("container_name")
491
+ force = kwargs.get("force", False)
492
+
493
+ if not container_id:
494
+ return {
495
+ "status": "error",
496
+ "container_removed": False,
497
+ "error": "container_id or container_name is required",
498
+ }
499
+
500
+ try:
501
+ result = await self.docker_integration.remove_container(container_id, force)
502
+
503
+ return {
504
+ "status": result.get("status", "unknown"),
505
+ "container_removed": result.get("status") == "removed",
506
+ "result": result,
507
+ }
508
+
509
+ except Exception as e:
510
+ return {
511
+ "status": "error",
512
+ "container_removed": False,
513
+ "error": f"Failed to remove container: {str(e)}",
514
+ }
515
+
516
+ async def _get_container_status(self, **kwargs) -> Dict[str, Any]:
517
+ """Get Docker container status."""
518
+ if not self.docker_integration:
519
+ await self._initialize_docker(**kwargs)
520
+
521
+ container_id = kwargs.get("container_id") or kwargs.get("container_name")
522
+
523
+ if not container_id:
524
+ return {
525
+ "status": "error",
526
+ "error": "container_id or container_name is required",
527
+ }
528
+
529
+ try:
530
+ status = await self.docker_integration.get_container_status(container_id)
531
+
532
+ return {"status": "success", "result": status}
533
+
534
+ except Exception as e:
535
+ return {
536
+ "status": "error",
537
+ "error": f"Failed to get container status: {str(e)}",
538
+ }
539
+
540
+ async def _list_containers(self, **kwargs) -> Dict[str, Any]:
541
+ """List Docker containers."""
542
+ if not self.docker_integration:
543
+ await self._initialize_docker(**kwargs)
544
+
545
+ all_containers = kwargs.get("all_containers", False)
546
+ filters = kwargs.get("filters", {})
547
+
548
+ try:
549
+ containers = await self.docker_integration.list_containers(
550
+ all_containers, filters
551
+ )
552
+
553
+ return {
554
+ "status": "success",
555
+ "containers": containers,
556
+ "result": {
557
+ "container_count": len(containers),
558
+ "containers": containers,
559
+ },
560
+ }
561
+
562
+ except Exception as e:
563
+ return {
564
+ "status": "error",
565
+ "containers": [],
566
+ "error": f"Failed to list containers: {str(e)}",
567
+ }
568
+
569
+ async def _create_service(self, **kwargs) -> Dict[str, Any]:
570
+ """Create Docker Swarm service."""
571
+ if not self.docker_integration:
572
+ await self._initialize_docker(**kwargs)
573
+
574
+ service_name = kwargs.get("service_name")
575
+ image = kwargs.get("image")
576
+
577
+ if not service_name or not image:
578
+ return {
579
+ "status": "error",
580
+ "service_created": False,
581
+ "error": "service_name and image are required",
582
+ }
583
+
584
+ try:
585
+ # Create service specification
586
+ service_spec = ServiceSpec(
587
+ name=service_name,
588
+ image=image,
589
+ replicas=kwargs.get("replicas", 1),
590
+ command=kwargs.get("command"),
591
+ environment=kwargs.get("environment", {}),
592
+ ports=kwargs.get("ports", []),
593
+ volumes=kwargs.get("volumes", []),
594
+ constraints=kwargs.get("constraints", []),
595
+ placement_preferences=kwargs.get("placement_preferences", []),
596
+ restart_policy=kwargs.get("restart_policy"),
597
+ update_config=kwargs.get("update_config"),
598
+ rollback_config=kwargs.get("rollback_config"),
599
+ labels=kwargs.get("labels", {}),
600
+ edge_node=kwargs.get("edge_node"),
601
+ )
602
+
603
+ # Create service
604
+ result = await self.docker_integration.create_service(service_spec)
605
+
606
+ return {
607
+ "status": result.get("status", "unknown"),
608
+ "service_created": result.get("status") == "created",
609
+ "result": result,
610
+ }
611
+
612
+ except Exception as e:
613
+ return {
614
+ "status": "error",
615
+ "service_created": False,
616
+ "error": f"Failed to create service: {str(e)}",
617
+ }
618
+
619
+ async def _update_service(self, **kwargs) -> Dict[str, Any]:
620
+ """Update Docker Swarm service."""
621
+ if not self.docker_integration:
622
+ await self._initialize_docker(**kwargs)
623
+
624
+ service_id = kwargs.get("service_id") or kwargs.get("service_name")
625
+
626
+ if not service_id:
627
+ return {
628
+ "status": "error",
629
+ "service_updated": False,
630
+ "error": "service_id or service_name is required",
631
+ }
632
+
633
+ try:
634
+ # Get current service spec and update it
635
+ # For simplicity, we'll create a new spec with updated values
636
+ service_spec = ServiceSpec(
637
+ name=kwargs.get("service_name", service_id),
638
+ image=kwargs.get("image", ""),
639
+ replicas=kwargs.get("replicas", 1),
640
+ command=kwargs.get("command"),
641
+ environment=kwargs.get("environment", {}),
642
+ labels=kwargs.get("labels", {}),
643
+ edge_node=kwargs.get("edge_node"),
644
+ )
645
+
646
+ result = await self.docker_integration.update_service(
647
+ service_id, service_spec
648
+ )
649
+
650
+ return {
651
+ "status": result.get("status", "unknown"),
652
+ "service_updated": result.get("status") == "updated",
653
+ "result": result,
654
+ }
655
+
656
+ except Exception as e:
657
+ return {
658
+ "status": "error",
659
+ "service_updated": False,
660
+ "error": f"Failed to update service: {str(e)}",
661
+ }
662
+
663
+ async def _scale_service(self, **kwargs) -> Dict[str, Any]:
664
+ """Scale Docker Swarm service."""
665
+ if not self.docker_integration:
666
+ await self._initialize_docker(**kwargs)
667
+
668
+ service_id = kwargs.get("service_id") or kwargs.get("service_name")
669
+ replicas = kwargs.get("replicas")
670
+
671
+ if not service_id or replicas is None:
672
+ return {
673
+ "status": "error",
674
+ "service_scaled": False,
675
+ "error": "service_id (or service_name) and replicas are required",
676
+ }
677
+
678
+ try:
679
+ result = await self.docker_integration.scale_service(service_id, replicas)
680
+
681
+ return {
682
+ "status": result.get("status", "unknown"),
683
+ "service_scaled": result.get("status") == "scaled",
684
+ "result": result,
685
+ }
686
+
687
+ except Exception as e:
688
+ return {
689
+ "status": "error",
690
+ "service_scaled": False,
691
+ "error": f"Failed to scale service: {str(e)}",
692
+ }
693
+
694
+ async def _get_service_status(self, **kwargs) -> Dict[str, Any]:
695
+ """Get Docker Swarm service status."""
696
+ if not self.docker_integration:
697
+ await self._initialize_docker(**kwargs)
698
+
699
+ service_id = kwargs.get("service_id") or kwargs.get("service_name")
700
+
701
+ if not service_id:
702
+ return {
703
+ "status": "error",
704
+ "error": "service_id or service_name is required",
705
+ }
706
+
707
+ try:
708
+ status = await self.docker_integration.get_service_status(service_id)
709
+
710
+ return {"status": "success", "result": status}
711
+
712
+ except Exception as e:
713
+ return {
714
+ "status": "error",
715
+ "error": f"Failed to get service status: {str(e)}",
716
+ }
717
+
718
+ async def _collect_metrics(self, **kwargs) -> Dict[str, Any]:
719
+ """Collect container metrics."""
720
+ if not self.docker_integration:
721
+ await self._initialize_docker(**kwargs)
722
+
723
+ container_id = kwargs.get("container_id") or kwargs.get("container_name")
724
+
725
+ if not container_id:
726
+ return {
727
+ "status": "error",
728
+ "error": "container_id or container_name is required",
729
+ }
730
+
731
+ try:
732
+ metrics = await self.docker_integration.collect_container_metrics(
733
+ container_id
734
+ )
735
+
736
+ if metrics:
737
+ return {
738
+ "status": "success",
739
+ "metrics": metrics.to_dict(),
740
+ "result": metrics.to_dict(),
741
+ }
742
+ else:
743
+ return {
744
+ "status": "error",
745
+ "metrics": {},
746
+ "error": "Failed to collect metrics",
747
+ }
748
+
749
+ except Exception as e:
750
+ return {
751
+ "status": "error",
752
+ "metrics": {},
753
+ "error": f"Failed to collect metrics: {str(e)}",
754
+ }
755
+
756
+ async def _get_system_info(self, **kwargs) -> Dict[str, Any]:
757
+ """Get Docker system information."""
758
+ if not self.docker_integration:
759
+ await self._initialize_docker(**kwargs)
760
+
761
+ try:
762
+ system_info = await self.docker_integration.get_system_info()
763
+
764
+ return {
765
+ "status": "success",
766
+ "system_info": system_info,
767
+ "result": system_info,
768
+ }
769
+
770
+ except Exception as e:
771
+ return {
772
+ "status": "error",
773
+ "system_info": {},
774
+ "error": f"Failed to get system info: {str(e)}",
775
+ }
776
+
777
+ async def _start_monitoring(self, **kwargs) -> Dict[str, Any]:
778
+ """Start Docker monitoring."""
779
+ if not self.docker_integration:
780
+ await self._initialize_docker(**kwargs)
781
+
782
+ try:
783
+ await self.docker_integration.start_monitoring()
784
+
785
+ return {
786
+ "status": "success",
787
+ "monitoring_started": True,
788
+ "result": {
789
+ "message": "Docker monitoring started",
790
+ "monitoring_interval": self.docker_integration.monitoring_interval,
791
+ "metrics_interval": self.docker_integration.metrics_interval,
792
+ },
793
+ }
794
+
795
+ except Exception as e:
796
+ return {
797
+ "status": "error",
798
+ "monitoring_started": False,
799
+ "error": f"Failed to start monitoring: {str(e)}",
800
+ }
801
+
802
+ async def _stop_monitoring(self, **kwargs) -> Dict[str, Any]:
803
+ """Stop Docker monitoring."""
804
+ if not self.docker_integration:
805
+ return {
806
+ "status": "error",
807
+ "monitoring_stopped": False,
808
+ "error": "Docker integration not initialized",
809
+ }
810
+
811
+ try:
812
+ await self.docker_integration.stop_monitoring()
813
+
814
+ return {
815
+ "status": "success",
816
+ "monitoring_stopped": True,
817
+ "result": {"message": "Docker monitoring stopped"},
818
+ }
819
+
820
+ except Exception as e:
821
+ return {
822
+ "status": "error",
823
+ "monitoring_stopped": False,
824
+ "error": f"Failed to stop monitoring: {str(e)}",
825
+ }