11import os
22import yaml
33import subprocess
4- import base64
54import time
65import logging
76from interface import KubernetesClusterPlugin
87
98logger = logging .getLogger ("PluginClusterStacks" )
109
10+
1111# Helper functions
1212def wait_for_pods (self , namespaces , timeout = 240 , interval = 15 , kubeconfig = None ):
1313 """
@@ -27,13 +27,19 @@ def wait_for_pods(self, namespaces, timeout=240, interval=15, kubeconfig=None):
2727 for namespace in namespaces :
2828 try :
2929 # Get pod status in the namespace
30- wait_pods_command = (
31- f"kubectl wait -n { namespace } --for=condition=Ready --timeout={ timeout } s pod --all"
30+ wait_pods_command = f"kubectl wait --kubeconfig={ kubeconfig } -n { namespace } --for=condition=Ready --timeout={ timeout } s pod --all"
31+ result = self ._run_subprocess (
32+ wait_pods_command ,
33+ f"Error fetching pods in { namespace } " ,
34+ shell = True ,
35+ capture_output = True ,
36+ text = True ,
3237 )
33- result = self ._run_subprocess (wait_pods_command , f"Error fetching pods in { namespace } " , shell = True , capture_output = True , text = True , kubeconfig = kubeconfig )
3438
3539 if result .returncode != 0 :
36- logger .warning (f"Not all pods in namespace { namespace } are ready. Details: { result .stderr } " )
40+ logger .warning (
41+ f"Not all pods in namespace { namespace } are ready. Details: { result .stderr } "
42+ )
3743 all_pods_ready = False
3844 else :
3945 logger .info (f"All pods in namespace { namespace } are ready." )
@@ -49,69 +55,87 @@ def wait_for_pods(self, namespaces, timeout=240, interval=15, kubeconfig=None):
4955 logger .info ("Waiting for all pods in specified namespaces to become ready..." )
5056 time .sleep (interval )
5157
52- raise TimeoutError (f"Timed out after { timeout } seconds waiting for pods in namespaces { namespaces } to become ready." )
58+ raise TimeoutError (
59+ f"Timed out after { timeout } seconds waiting for pods in namespaces { namespaces } to become ready."
60+ )
5361
5462
5563def load_config (config_path ):
5664 """
5765 Loads the configuration from a YAML file.
5866 """
5967
60- with open (config_path , 'r' ) as file :
68+ with open (config_path , "r" ) as file :
6169 config = yaml .safe_load (file ) or {}
6270 return config
6371
72+
6473class PluginClusterStacksRemoteAPI (KubernetesClusterPlugin ):
6574 def __init__ (self , config_file = None ):
6675 self .config = load_config (config_file ) if config_file else {}
6776 logger .debug (self .config )
6877 self .working_directory = os .getcwd ()
6978 logger .debug (f"Working from { self .working_directory } " )
70- self .kubeconfig_mgmnt = self .config ['kubeconfig' ]
71- self .workloadclusters = self .config ['workloadcluster' ]
72- self .cs_namespace = self .config ['namespace' ]
73-
79+ self .kubeconfig_mgmnt = self .config ["kubeconfig" ]
80+ self .workloadclusters = self .config ["workloadcluster" ]
81+ self .cs_namespace = self .config ["namespace" ]
7482
7583 def create_cluster (self , cluster_name = None , version = None , kubeconfig_filepath = None ):
7684 self .cluster_name = cluster_name
7785 self .cluster_version = version
7886 self .kubeconfig_cs_cluster = kubeconfig_filepath
7987
8088 # Create workload cluster
81- self ._apply_yaml (self .workloadclusters , "Error applying cluster.yaml" , kubeconfig = self .kubeconfig_mgmnt )
89+ self ._apply_yaml (
90+ self .workloadclusters ,
91+ "Error applying cluster.yaml" ,
92+ kubeconfig = self .kubeconfig_mgmnt ,
93+ )
8294
83- #TODO:!!! We also need to introduce a waiting function here
95+ # TODO:!!! We also need to introduce a waiting function here
8496
8597 print ("retrieve kubeconfig to path" )
86- self ._retrieve_kubeconfig (namespace = self .cs_namespace , kubeconfig = self .kubeconfig_mgmnt )
98+ self ._retrieve_kubeconfig (
99+ namespace = self .cs_namespace , kubeconfig = self .kubeconfig_mgmnt
100+ )
87101
88102 # Wait for workload system pods to be ready
89103 # wait_for_workload_pods_ready(kubeconfig_path=self.kubeconfig_cs_cluster)
90104 # ~ wait_for_pods(self, ["kube-system"], timeout=600, interval=15, kubeconfig=self.kubeconfig_cs_cluster)
91105
92-
93- def delete_cluster (self , cluster_name = None ): #TODO:!!! need to adjust delete method
106+ def delete_cluster (
107+ self , cluster_name = None
108+ ): # TODO:!!! need to adjust delete method
94109 self .cluster_name = cluster_name
95- #Get the name of the workloadcluster from the config file
110+ # Get the name of the workloadcluster from the config file
96111 workload_cluster_config = load_config (self .workloadclusters )
97- workload_cluster_name = workload_cluster_config [' metadata' ][ ' name' ]
112+ workload_cluster_name = workload_cluster_config [" metadata" ][ " name" ]
98113 try :
99114 # Check if the cluster exists
100115 check_cluster_command = f"kubectl --kubeconfig={ self .kubeconfig_mgmnt } get cluster { workload_cluster_name } -n { self .cs_namespace } "
101- result = self ._run_subprocess (check_cluster_command , "Failed to get cluster resource" , shell = True , capture_output = True , text = True )
116+ result = self ._run_subprocess (
117+ check_cluster_command ,
118+ "Failed to get cluster resource" ,
119+ shell = True ,
120+ capture_output = True ,
121+ text = True ,
122+ )
102123
103124 # Proceed with deletion only if the cluster exists
104125 if result .returncode == 0 :
105126 delete_command = f"kubectl --kubeconfig={ self .kubeconfig_mgmnt } delete cluster { workload_cluster_name } --timeout=600s -n { self .cs_namespace } "
106- self ._run_subprocess (delete_command , "Timeout while deleting the cluster" , shell = True )
127+ self ._run_subprocess (
128+ delete_command , "Timeout while deleting the cluster" , shell = True
129+ )
107130
108131 except subprocess .CalledProcessError as error :
109132 if "NotFound" in error .stderr :
110- logger .info (f"Cluster { workload_cluster_name } not found. Skipping deletion." )
133+ logger .info (
134+ f"Cluster { workload_cluster_name } not found. Skipping deletion."
135+ )
111136 else :
112137 raise RuntimeError (f"Error checking for cluster existence: { error } " )
113138
114-
115139 def _apply_yaml (self , yaml_file , error_msg , kubeconfig = None ):
116140 """
117141 Applies a Kubernetes YAML configuration file to the cluster, substituting environment variables as needed.
@@ -132,7 +156,6 @@ def _apply_yaml(self, yaml_file, error_msg, kubeconfig=None):
132156 except subprocess .CalledProcessError as error :
133157 raise RuntimeError (f"{ error_msg } : { error } " )
134158
135-
136159 def _retrieve_kubeconfig (self , namespace = "default" , kubeconfig = None ):
137160 """
138161 Retrieves the kubeconfig for the specified cluster and saves it to a local file.
@@ -141,25 +164,28 @@ def _retrieve_kubeconfig(self, namespace="default", kubeconfig=None):
141164 :param kubeconfig: Optional path to the kubeconfig file for the target Kubernetes cluster.
142165 """
143166
144- #Get the name of the workloadcluster from the config file
167+ # Get the name of the workloadcluster from the config file
145168 workload_cluster_config = load_config (self .workloadclusters )
146- workload_cluster_name = workload_cluster_config [' metadata' ][ ' name' ]
169+ workload_cluster_name = workload_cluster_config [" metadata" ][ " name" ]
147170
148171 command_args = [
149172 "kubectl " ,
150173 f"--kubeconfig={ self .kubeconfig_mgmnt } " ,
151174 f"-n { self .cs_namespace } " ,
152- f"get secret { workload_cluster_name } -kubeconfig" ,
175+ f"get secret { workload_cluster_name } -kubeconfig" ,
153176 "-o go-template='{{.data.value|base64decode}}'" ,
154177 f"> { self .kubeconfig_cs_cluster } " ,
155178 ]
156179 kubeconfig_command = ""
157180 for entry in command_args :
158181 kubeconfig_command += entry + " "
159- self ._run_subprocess (kubeconfig_command , "Error retrieving kubeconfig" , shell = True )
160-
182+ self ._run_subprocess (
183+ kubeconfig_command , "Error retrieving kubeconfig" , shell = True
184+ )
161185
162- def _run_subprocess (self , command , error_msg , shell = False , capture_output = False , text = False ):
186+ def _run_subprocess (
187+ self , command , error_msg , shell = False , capture_output = False , text = False
188+ ):
163189 """
164190 Executes a subprocess command with the specified environment variables and parameters.
165191
@@ -172,7 +198,13 @@ def _run_subprocess(self, command, error_msg, shell=False, capture_output=False,
172198 """
173199 try :
174200 # Run the subprocess
175- result = subprocess .run (command , shell = shell , capture_output = capture_output , text = text , check = True )
201+ result = subprocess .run (
202+ command ,
203+ shell = shell ,
204+ capture_output = capture_output ,
205+ text = text ,
206+ check = True ,
207+ )
176208 return result
177209 except subprocess .CalledProcessError as error :
178210 logger .error (f"{ error_msg } : { error } " )
0 commit comments