agentscope-runtime 0.1.5b1__py3-none-any.whl → 0.1.6__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 (90) hide show
  1. agentscope_runtime/engine/agents/agentscope_agent.py +447 -0
  2. agentscope_runtime/engine/agents/agno_agent.py +19 -18
  3. agentscope_runtime/engine/agents/autogen_agent.py +13 -8
  4. agentscope_runtime/engine/agents/utils.py +53 -0
  5. agentscope_runtime/engine/deployers/__init__.py +0 -13
  6. agentscope_runtime/engine/deployers/local_deployer.py +501 -356
  7. agentscope_runtime/engine/helpers/helper.py +60 -41
  8. agentscope_runtime/engine/runner.py +11 -36
  9. agentscope_runtime/engine/schemas/agent_schemas.py +2 -70
  10. agentscope_runtime/engine/services/sandbox_service.py +62 -70
  11. agentscope_runtime/engine/services/tablestore_memory_service.py +304 -0
  12. agentscope_runtime/engine/services/tablestore_rag_service.py +143 -0
  13. agentscope_runtime/engine/services/tablestore_session_history_service.py +293 -0
  14. agentscope_runtime/engine/services/utils/tablestore_service_utils.py +352 -0
  15. agentscope_runtime/sandbox/__init__.py +2 -0
  16. agentscope_runtime/sandbox/box/base/__init__.py +4 -0
  17. agentscope_runtime/sandbox/box/base/base_sandbox.py +4 -3
  18. agentscope_runtime/sandbox/box/browser/__init__.py +4 -0
  19. agentscope_runtime/sandbox/box/browser/browser_sandbox.py +8 -13
  20. agentscope_runtime/sandbox/box/dummy/__init__.py +4 -0
  21. agentscope_runtime/sandbox/box/filesystem/__init__.py +4 -0
  22. agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +8 -6
  23. agentscope_runtime/sandbox/box/gui/__init__.py +4 -0
  24. agentscope_runtime/sandbox/box/gui/gui_sandbox.py +80 -0
  25. agentscope_runtime/sandbox/box/sandbox.py +5 -2
  26. agentscope_runtime/sandbox/box/shared/routers/generic.py +20 -1
  27. agentscope_runtime/sandbox/box/training_box/__init__.py +4 -0
  28. agentscope_runtime/sandbox/box/training_box/training_box.py +10 -15
  29. agentscope_runtime/sandbox/build.py +143 -58
  30. agentscope_runtime/sandbox/client/http_client.py +43 -49
  31. agentscope_runtime/sandbox/client/training_client.py +0 -1
  32. agentscope_runtime/sandbox/constant.py +24 -1
  33. agentscope_runtime/sandbox/custom/custom_sandbox.py +5 -5
  34. agentscope_runtime/sandbox/custom/example.py +2 -2
  35. agentscope_runtime/sandbox/enums.py +1 -0
  36. agentscope_runtime/sandbox/manager/collections/in_memory_mapping.py +11 -6
  37. agentscope_runtime/sandbox/manager/collections/redis_mapping.py +25 -9
  38. agentscope_runtime/sandbox/manager/container_clients/__init__.py +0 -10
  39. agentscope_runtime/sandbox/manager/container_clients/agentrun_client.py +1098 -0
  40. agentscope_runtime/sandbox/manager/container_clients/docker_client.py +33 -205
  41. agentscope_runtime/sandbox/manager/container_clients/kubernetes_client.py +8 -555
  42. agentscope_runtime/sandbox/manager/sandbox_manager.py +187 -88
  43. agentscope_runtime/sandbox/manager/server/app.py +82 -14
  44. agentscope_runtime/sandbox/manager/server/config.py +50 -3
  45. agentscope_runtime/sandbox/model/container.py +6 -23
  46. agentscope_runtime/sandbox/model/manager_config.py +93 -5
  47. agentscope_runtime/sandbox/tools/gui/__init__.py +7 -0
  48. agentscope_runtime/sandbox/tools/gui/tool.py +77 -0
  49. agentscope_runtime/sandbox/tools/mcp_tool.py +6 -2
  50. agentscope_runtime/sandbox/utils.py +124 -0
  51. agentscope_runtime/version.py +1 -1
  52. {agentscope_runtime-0.1.5b1.dist-info → agentscope_runtime-0.1.6.dist-info}/METADATA +168 -77
  53. {agentscope_runtime-0.1.5b1.dist-info → agentscope_runtime-0.1.6.dist-info}/RECORD +59 -78
  54. {agentscope_runtime-0.1.5b1.dist-info → agentscope_runtime-0.1.6.dist-info}/entry_points.txt +0 -1
  55. agentscope_runtime/engine/agents/agentscope_agent/__init__.py +0 -6
  56. agentscope_runtime/engine/agents/agentscope_agent/agent.py +0 -401
  57. agentscope_runtime/engine/agents/agentscope_agent/hooks.py +0 -169
  58. agentscope_runtime/engine/agents/llm_agent.py +0 -51
  59. agentscope_runtime/engine/deployers/adapter/responses/response_api_adapter_utils.py +0 -2886
  60. agentscope_runtime/engine/deployers/adapter/responses/response_api_agent_adapter.py +0 -51
  61. agentscope_runtime/engine/deployers/adapter/responses/response_api_protocol_adapter.py +0 -314
  62. agentscope_runtime/engine/deployers/cli_fc_deploy.py +0 -143
  63. agentscope_runtime/engine/deployers/kubernetes_deployer.py +0 -265
  64. agentscope_runtime/engine/deployers/modelstudio_deployer.py +0 -626
  65. agentscope_runtime/engine/deployers/utils/deployment_modes.py +0 -14
  66. agentscope_runtime/engine/deployers/utils/docker_image_utils/__init__.py +0 -8
  67. agentscope_runtime/engine/deployers/utils/docker_image_utils/docker_image_builder.py +0 -429
  68. agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +0 -240
  69. agentscope_runtime/engine/deployers/utils/docker_image_utils/runner_image_factory.py +0 -297
  70. agentscope_runtime/engine/deployers/utils/package_project_utils.py +0 -932
  71. agentscope_runtime/engine/deployers/utils/service_utils/__init__.py +0 -9
  72. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +0 -504
  73. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_templates.py +0 -157
  74. agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +0 -268
  75. agentscope_runtime/engine/deployers/utils/service_utils/service_config.py +0 -75
  76. agentscope_runtime/engine/deployers/utils/service_utils/service_factory.py +0 -220
  77. agentscope_runtime/engine/deployers/utils/wheel_packager.py +0 -389
  78. agentscope_runtime/engine/helpers/agent_api_builder.py +0 -651
  79. agentscope_runtime/engine/llms/__init__.py +0 -3
  80. agentscope_runtime/engine/llms/base_llm.py +0 -60
  81. agentscope_runtime/engine/llms/qwen_llm.py +0 -47
  82. agentscope_runtime/engine/schemas/embedding.py +0 -37
  83. agentscope_runtime/engine/schemas/modelstudio_llm.py +0 -310
  84. agentscope_runtime/engine/schemas/oai_llm.py +0 -538
  85. agentscope_runtime/engine/schemas/realtime.py +0 -254
  86. /agentscope_runtime/engine/{deployers/adapter/responses → services/utils}/__init__.py +0 -0
  87. /agentscope_runtime/{engine/deployers/utils → sandbox/box/gui/box}/__init__.py +0 -0
  88. {agentscope_runtime-0.1.5b1.dist-info → agentscope_runtime-0.1.6.dist-info}/WHEEL +0 -0
  89. {agentscope_runtime-0.1.5b1.dist-info → agentscope_runtime-0.1.6.dist-info}/licenses/LICENSE +0 -0
  90. {agentscope_runtime-0.1.5b1.dist-info → agentscope_runtime-0.1.6.dist-info}/top_level.txt +0 -0
@@ -1,12 +1,10 @@
1
1
  # -*- coding: utf-8 -*-
2
- # pylint: disable=too-many-branches, self-assigning-variable
3
- # pylint: disable=too-many-statements
4
-
5
- import hashlib
6
- import logging
2
+ # pylint: disable=too-many-branches
3
+ import os
7
4
  import time
5
+ import hashlib
8
6
  import traceback
9
- from typing import Optional, Tuple
7
+ import logging
10
8
 
11
9
  from kubernetes import client
12
10
  from kubernetes import config as k8s_config
@@ -16,19 +14,12 @@ from .base_client import BaseClient
16
14
 
17
15
  logger = logging.getLogger(__name__)
18
16
 
19
- DEFAULT_IMAGE_REGISTRY = "agentscope-registry.ap-southeast-1.cr.aliyuncs.com"
20
-
21
17
 
22
18
  class KubernetesClient(BaseClient):
23
- def __init__(
24
- self,
25
- config=None,
26
- image_registry: Optional[str] = DEFAULT_IMAGE_REGISTRY,
27
- ):
19
+ def __init__(self, config=None):
28
20
  self.config = config
29
21
  namespace = self.config.k8s_namespace
30
22
  kubeconfig = self.config.kubeconfig_path
31
- self.image_registry = image_registry
32
23
  try:
33
24
  if kubeconfig:
34
25
  k8s_config.load_kube_config(config_file=kubeconfig)
@@ -40,7 +31,6 @@ class KubernetesClient(BaseClient):
40
31
  except k8s_config.ConfigException:
41
32
  k8s_config.load_kube_config()
42
33
  self.v1 = client.CoreV1Api()
43
- self.apps_v1 = client.AppsV1Api() # For Deployments
44
34
  self.namespace = namespace
45
35
  # Test connection
46
36
  self.v1.list_namespace()
@@ -55,61 +45,6 @@ class KubernetesClient(BaseClient):
55
45
  "• For in-cluster: ensure proper RBAC permissions",
56
46
  ) from e
57
47
 
58
- def _is_local_cluster(self):
59
- """
60
- Determine if we're connected to a local Kubernetes cluster.
61
-
62
- Returns:
63
- bool: True if connected to a local cluster, False otherwise
64
- """
65
- try:
66
- # Get the current context configuration
67
- contexts, current_context = k8s_config.list_kube_config_contexts(
68
- config_file=self.config.kubeconfig_path
69
- if hasattr(self.config, "kubeconfig_path")
70
- and self.config.kubeconfig_path
71
- else None,
72
- )
73
-
74
- if current_context and current_context.get("context"):
75
- cluster_name = current_context["context"].get("cluster", "")
76
- server = None
77
-
78
- # Get cluster server URL
79
- for cluster in contexts.get("clusters", []):
80
- if cluster["name"] == cluster_name:
81
- server = cluster.get("cluster", {}).get("server", "")
82
- break
83
-
84
- if server:
85
- # Check for common local cluster patterns
86
- local_patterns = [
87
- "localhost",
88
- "127.0.0.1",
89
- "0.0.0.0",
90
- "docker-desktop",
91
- "kind-", # kind clusters
92
- "minikube", # minikube
93
- "k3d-", # k3d clusters
94
- "colima", # colima
95
- ]
96
-
97
- server_lower = server.lower()
98
- cluster_lower = cluster_name.lower()
99
-
100
- for pattern in local_patterns:
101
- if pattern in server_lower or pattern in cluster_lower:
102
- return True
103
-
104
- return False
105
-
106
- except Exception as e:
107
- logger.debug(
108
- f"Could not determine cluster type, assuming remote: {e}",
109
- )
110
- # If we can't determine, assume remote for safety
111
- return False
112
-
113
48
  def _parse_port_spec(self, port_spec):
114
49
  """
115
50
  Parse port specification.
@@ -157,13 +92,6 @@ class KubernetesClient(BaseClient):
157
92
  container_name = name or "main-container"
158
93
 
159
94
  # Container specification
160
- # TODO: use image from docker registry first
161
-
162
- if not self.image_registry:
163
- image = image
164
- else:
165
- image = f"{self.image_registry}/{image}"
166
-
167
95
  container = client.V1Container(
168
96
  name=container_name,
169
97
  image=image,
@@ -634,8 +562,9 @@ class KubernetesClient(BaseClient):
634
562
  def _get_pod_node_ip(self, pod_name):
635
563
  """Get the IP of the node where the pod is running"""
636
564
 
637
- # Check if we are using a local Kubernetes cluster
638
- if self._is_local_cluster():
565
+ # Check if we are running in Colima, where pod runs in VM
566
+ docker_host = os.getenv("DOCKER_HOST", "")
567
+ if "colima" in docker_host.lower():
639
568
  return "localhost"
640
569
 
641
570
  try:
@@ -672,479 +601,3 @@ class KubernetesClient(BaseClient):
672
601
  except Exception as e:
673
602
  logger.error(f"Failed to get pod node IP: {e}")
674
603
  return None
675
-
676
- def _create_deployment_spec(
677
- self,
678
- image,
679
- name,
680
- ports=None,
681
- volumes=None,
682
- environment=None,
683
- runtime_config=None,
684
- replicas=1,
685
- ):
686
- """Create a Kubernetes Deployment specification."""
687
- if runtime_config is None:
688
- runtime_config = {}
689
-
690
- container_name = name or "main-container"
691
-
692
- # Use image registry if configured
693
- if not self.image_registry:
694
- full_image = image
695
- else:
696
- full_image = f"{self.image_registry}/{image}"
697
-
698
- # Create container spec (reuse the existing pod spec logic)
699
- container = client.V1Container(
700
- name=container_name,
701
- image=full_image,
702
- image_pull_policy=runtime_config.get(
703
- "image_pull_policy",
704
- "IfNotPresent",
705
- ),
706
- )
707
-
708
- # Configure ports
709
- if ports:
710
- container_ports = []
711
- for port_spec in ports:
712
- port_info = self._parse_port_spec(port_spec)
713
- if port_info:
714
- container_ports.append(
715
- client.V1ContainerPort(
716
- container_port=port_info["port"],
717
- protocol=port_info["protocol"],
718
- ),
719
- )
720
- if container_ports:
721
- container.ports = container_ports
722
-
723
- # Configure environment variables
724
- if environment:
725
- env_vars = []
726
- for key, value in environment.items():
727
- env_vars.append(client.V1EnvVar(name=key, value=str(value)))
728
- container.env = env_vars
729
-
730
- # Configure volume mounts and volumes
731
- volume_mounts = []
732
- pod_volumes = []
733
- if volumes:
734
- for volume_idx, (host_path, mount_info) in enumerate(
735
- volumes.items(),
736
- ):
737
- if isinstance(mount_info, dict):
738
- container_path = mount_info["bind"]
739
- mode = mount_info.get("mode", "rw")
740
- else:
741
- container_path = mount_info
742
- mode = "rw"
743
- volume_name = f"vol-{volume_idx}"
744
-
745
- # Create volume mount
746
- volume_mounts.append(
747
- client.V1VolumeMount(
748
- name=volume_name,
749
- mount_path=container_path,
750
- read_only=(mode == "ro"),
751
- ),
752
- )
753
- # Create host path volume
754
- pod_volumes.append(
755
- client.V1Volume(
756
- name=volume_name,
757
- host_path=client.V1HostPathVolumeSource(
758
- path=host_path,
759
- ),
760
- ),
761
- )
762
-
763
- if volume_mounts:
764
- container.volume_mounts = volume_mounts
765
-
766
- # Apply runtime config to container
767
- if "resources" in runtime_config:
768
- container.resources = client.V1ResourceRequirements(
769
- **runtime_config["resources"],
770
- )
771
-
772
- if "security_context" in runtime_config:
773
- container.security_context = client.V1SecurityContext(
774
- **runtime_config["security_context"],
775
- )
776
-
777
- # Pod template specification
778
- pod_spec = client.V1PodSpec(
779
- containers=[container],
780
- restart_policy=runtime_config.get(
781
- "restart_policy",
782
- "Always",
783
- ), # Deployments typically use Always
784
- )
785
-
786
- if pod_volumes:
787
- pod_spec.volumes = pod_volumes
788
-
789
- if "node_selector" in runtime_config:
790
- pod_spec.node_selector = runtime_config["node_selector"]
791
-
792
- if "tolerations" in runtime_config:
793
- pod_spec.tolerations = runtime_config["tolerations"]
794
-
795
- # Handle image pull secrets
796
- image_pull_secrets = runtime_config.get("image_pull_secrets", [])
797
- if image_pull_secrets:
798
- secrets = []
799
- for secret_name in image_pull_secrets:
800
- secrets.append(client.V1LocalObjectReference(name=secret_name))
801
- pod_spec.image_pull_secrets = secrets
802
-
803
- # Pod template
804
- pod_template = client.V1PodTemplateSpec(
805
- metadata=client.V1ObjectMeta(
806
- labels={
807
- "app": name,
808
- "created-by": "kubernetes-client",
809
- },
810
- ),
811
- spec=pod_spec,
812
- )
813
-
814
- # Deployment specification
815
- deployment_spec = client.V1DeploymentSpec(
816
- replicas=replicas,
817
- selector=client.V1LabelSelector(
818
- match_labels={"app": name},
819
- ),
820
- template=pod_template,
821
- )
822
-
823
- return deployment_spec
824
-
825
- def _create_loadbalancer_service(self, deployment_name, port_list):
826
- """Create a LoadBalancer service for the deployment."""
827
- try:
828
- service_name = f"{deployment_name}-lb-service"
829
- selector = {"app": deployment_name}
830
-
831
- # Construct multi-port configuration
832
- service_ports = []
833
- for port_info in port_list:
834
- port = port_info["port"]
835
- protocol = port_info["protocol"]
836
- service_ports.append(
837
- client.V1ServicePort(
838
- name=f"port-{port}",
839
- port=port,
840
- target_port=port,
841
- protocol=protocol,
842
- ),
843
- )
844
-
845
- service_spec = client.V1ServiceSpec(
846
- selector=selector,
847
- ports=service_ports,
848
- type="LoadBalancer",
849
- )
850
-
851
- service = client.V1Service(
852
- api_version="v1",
853
- kind="Service",
854
- metadata=client.V1ObjectMeta(
855
- name=service_name,
856
- namespace=self.namespace,
857
- ),
858
- spec=service_spec,
859
- )
860
-
861
- # Create the service
862
- self.v1.create_namespaced_service(
863
- namespace=self.namespace,
864
- body=service,
865
- )
866
-
867
- logger.debug(
868
- f"LoadBalancer service '{service_name}' created successfully",
869
- )
870
- return True, service_name
871
- except Exception as e:
872
- logger.error(
873
- f"Failed to create LoadBalancer service for deployment "
874
- f"{deployment_name}: "
875
- f"{e}, {traceback.format_exc()}",
876
- )
877
- return False, None
878
-
879
- def create_deployment(
880
- self,
881
- image,
882
- name=None,
883
- ports=None,
884
- volumes=None,
885
- environment=None,
886
- runtime_config=None,
887
- replicas=1,
888
- create_service=True,
889
- ) -> Tuple[str, list, str] | Tuple[None, None, None]:
890
- """
891
- Create a new Kubernetes Deployment with LoadBalancer service.
892
-
893
- Args:
894
- image: Container image name
895
- name: Deployment name (auto-generated if None)
896
- ports: List of ports to expose
897
- volumes: Volume mounts dictionary
898
- environment: Environment variables dictionary
899
- runtime_config: Runtime configuration dictionary
900
- replicas: Number of replicas for the deployment
901
- create_service: Whether to create LoadBalancer service
902
-
903
- Returns:
904
- Tuple of (deployment_name, ports, load_balancer_ip)
905
- """
906
- if not name:
907
- name = f"deploy-{hashlib.md5(image.encode()).hexdigest()[:8]}"
908
-
909
- try:
910
- # Create deployment specification
911
- deployment_spec = self._create_deployment_spec(
912
- image,
913
- name,
914
- ports,
915
- volumes,
916
- environment,
917
- runtime_config,
918
- replicas,
919
- )
920
-
921
- # Create deployment metadata
922
- metadata = client.V1ObjectMeta(
923
- name=name,
924
- namespace=self.namespace,
925
- labels={
926
- "created-by": "kubernetes-client",
927
- "app": name,
928
- },
929
- )
930
-
931
- # Create deployment object
932
- deployment = client.V1Deployment(
933
- api_version="apps/v1",
934
- kind="Deployment",
935
- metadata=metadata,
936
- spec=deployment_spec,
937
- )
938
-
939
- # Create the deployment
940
- self.apps_v1.create_namespaced_deployment(
941
- namespace=self.namespace,
942
- body=deployment,
943
- )
944
-
945
- logger.debug(
946
- f"Deployment '{name}' created successfully in namespace "
947
- f"'{self.namespace}' with {replicas} replicas",
948
- )
949
-
950
- service_info = None
951
- load_balancer_ip = None
952
-
953
- # Create LoadBalancer service if requested and ports are specified
954
- if create_service and ports:
955
- parsed_ports = []
956
- for port_spec in ports:
957
- port_info = self._parse_port_spec(port_spec)
958
- if port_info:
959
- parsed_ports.append(port_info)
960
-
961
- if parsed_ports:
962
- (
963
- service_created,
964
- service_name,
965
- ) = self._create_loadbalancer_service(
966
- name,
967
- parsed_ports,
968
- )
969
- if service_created:
970
- service_info = {
971
- "name": service_name,
972
- "type": "LoadBalancer",
973
- "ports": [p["port"] for p in parsed_ports],
974
- }
975
- # Wait a bit and try to get LoadBalancer IP
976
- time.sleep(2)
977
- load_balancer_ip = self._get_loadbalancer_ip(
978
- service_name,
979
- )
980
-
981
- # Wait for deployment to be ready
982
- if not self.wait_for_deployment_ready(name, timeout=120):
983
- logger.warning(f"Deployment '{name}' may not be fully ready")
984
-
985
- logger.debug(
986
- f"Deployment '{name}' created successfully with service: "
987
- f"{service_info}",
988
- )
989
-
990
- return (
991
- name,
992
- service_info["ports"] if service_info else [],
993
- load_balancer_ip or "",
994
- )
995
-
996
- except Exception as e:
997
- logger.error(
998
- f"Failed to create deployment: {e}, {traceback.format_exc()}",
999
- )
1000
- return None, None, None
1001
-
1002
- def wait_for_deployment_ready(self, deployment_name, timeout=300):
1003
- """Wait for a deployment to be ready."""
1004
- start_time = time.time()
1005
- while time.time() - start_time < timeout:
1006
- try:
1007
- deployment = self.apps_v1.read_namespaced_deployment(
1008
- name=deployment_name,
1009
- namespace=self.namespace,
1010
- )
1011
-
1012
- # Check if deployment is ready
1013
- if (
1014
- deployment.status.ready_replicas
1015
- and deployment.status.ready_replicas
1016
- == deployment.spec.replicas
1017
- ):
1018
- return True
1019
-
1020
- time.sleep(3)
1021
- except ApiException as e:
1022
- if e.status == 404:
1023
- return False
1024
- time.sleep(3)
1025
- return False
1026
-
1027
- def _get_loadbalancer_ip(self, service_name, timeout=30):
1028
- """Get LoadBalancer external IP address."""
1029
- start_time = time.time()
1030
- while time.time() - start_time < timeout:
1031
- try:
1032
- service = self.v1.read_namespaced_service(
1033
- name=service_name,
1034
- namespace=self.namespace,
1035
- )
1036
-
1037
- if (
1038
- service.status.load_balancer
1039
- and service.status.load_balancer.ingress
1040
- ):
1041
- ingress = service.status.load_balancer.ingress[0]
1042
- # Return IP or hostname
1043
- return ingress.ip or ingress.hostname
1044
-
1045
- time.sleep(2)
1046
- except Exception as e:
1047
- logger.debug(f"Waiting for LoadBalancer IP: {e}")
1048
- time.sleep(2)
1049
-
1050
- logger.debug(
1051
- f"LoadBalancer IP not available for service {service_name}",
1052
- )
1053
- return None
1054
-
1055
- def remove_deployment(self, deployment_name, remove_service=True):
1056
- """Remove a Kubernetes Deployment and optionally its service."""
1057
- try:
1058
- # Remove associated LoadBalancer service first if requested
1059
- if remove_service:
1060
- service_name = f"{deployment_name}-lb-service"
1061
- try:
1062
- self.v1.delete_namespaced_service(
1063
- name=service_name,
1064
- namespace=self.namespace,
1065
- )
1066
- logger.debug(
1067
- f"Removed LoadBalancer service {service_name}",
1068
- )
1069
- except ApiException as e:
1070
- if e.status != 404:
1071
- logger.warning(
1072
- f"Failed to remove service {service_name}: {e}",
1073
- )
1074
-
1075
- # Remove the deployment
1076
- self.apps_v1.delete_namespaced_deployment(
1077
- name=deployment_name,
1078
- namespace=self.namespace,
1079
- body=client.V1DeleteOptions(
1080
- propagation_policy="Foreground",
1081
- ),
1082
- )
1083
-
1084
- logger.debug(
1085
- f"Deployment '{deployment_name}' removed successfully",
1086
- )
1087
- return True
1088
-
1089
- except ApiException as e:
1090
- if e.status == 404:
1091
- logger.warning(f"Deployment '{deployment_name}' not found")
1092
- return True
1093
- logger.error(f"Failed to remove deployment: {e.reason}")
1094
- return False
1095
- except Exception as e:
1096
- logger.error(f"An error occurred: {e}, {traceback.format_exc()}")
1097
- return False
1098
-
1099
- def get_deployment_status(self, deployment_name):
1100
- """Get the current status of the specified deployment."""
1101
- try:
1102
- deployment = self.apps_v1.read_namespaced_deployment(
1103
- name=deployment_name,
1104
- namespace=self.namespace,
1105
- )
1106
-
1107
- return {
1108
- "name": deployment_name,
1109
- "replicas": deployment.spec.replicas,
1110
- "ready_replicas": deployment.status.ready_replicas or 0,
1111
- "available_replicas": deployment.status.available_replicas
1112
- or 0,
1113
- "unavailable_replicas": deployment.status.unavailable_replicas
1114
- or 0,
1115
- "conditions": [
1116
- {
1117
- "type": condition.type,
1118
- "status": condition.status,
1119
- "reason": condition.reason,
1120
- "message": condition.message,
1121
- }
1122
- for condition in (deployment.status.conditions or [])
1123
- ],
1124
- }
1125
- except ApiException as e:
1126
- if e.status == 404:
1127
- logger.warning(f"Deployment '{deployment_name}' not found")
1128
- else:
1129
- logger.error(f"Failed to get deployment status: {e.reason}")
1130
- return None
1131
- except Exception as e:
1132
- logger.error(f"An error occurred: {e}, {traceback.format_exc()}")
1133
- return None
1134
-
1135
- def list_deployments(self, label_selector=None):
1136
- """List deployments in the namespace."""
1137
- try:
1138
- deployments = self.apps_v1.list_namespaced_deployment(
1139
- namespace=self.namespace,
1140
- label_selector=label_selector,
1141
- )
1142
- return [
1143
- deployment.metadata.name for deployment in deployments.items
1144
- ]
1145
- except ApiException as e:
1146
- logger.error(f"Failed to list deployments: {e.reason}")
1147
- return []
1148
- except Exception as e:
1149
- logger.error(f"An error occurred: {e}, {traceback.format_exc()}")
1150
- return []