@@ -64,14 +64,37 @@ async def _get_helm_version():
64
64
65
65
66
66
class KubernetesResponseWrapper (BaseStreamWrapper ):
67
+
68
+ def __init__ (self , stream ):
69
+ super ().__init__ (stream )
70
+ self .msg : bytes = bytes ()
71
+
67
72
async def read (self , size : int | None = None ):
68
- while not self .stream .closed :
73
+ if len (self .msg ) > 0 :
74
+ if len (self .msg ) > size :
75
+ data = self .msg [0 :size ]
76
+ self .msg = self .msg [size :]
77
+ return data
78
+ else :
79
+ data = self .msg
80
+ size -= len (self .msg )
81
+ self .msg = bytes ()
82
+ else :
83
+ data = bytes ()
84
+ while size > 0 and not self .stream .closed :
69
85
async for msg in self .stream :
70
86
channel = msg .data [0 ]
71
- data = msg .data [1 :]
72
- if data and channel == ws_client .STDOUT_CHANNEL :
73
- return data
74
- return None
87
+ self .msg = msg .data [1 :]
88
+ if self .msg and channel == ws_client .STDOUT_CHANNEL :
89
+ if len (self .msg ) > size :
90
+ data += self .msg [0 :size ]
91
+ self .msg = self .msg [size :]
92
+ return data
93
+ else :
94
+ data += self .msg
95
+ size -= len (self .msg )
96
+ self .msg = bytes ()
97
+ return data if len (data ) > 0 else None
75
98
76
99
async def write (self , data : Any ):
77
100
channel_prefix = bytes (chr (ws_client .STDIN_CHANNEL ), "ascii" )
@@ -116,7 +139,7 @@ def __init__(
116
139
)
117
140
self .inCluster = inCluster
118
141
self .kubeconfig = (
119
- kubeconfig
142
+ str ( Path ( kubeconfig ). expanduser ())
120
143
if kubeconfig is not None
121
144
else os .path .join (str (Path .home ()), ".kube" , "config" )
122
145
)
@@ -207,33 +230,18 @@ async def _copy_local_to_remote_single(
207
230
async def _copy_remote_to_local (
208
231
self , src : str , dst : str , location : Location , read_only : bool = False
209
232
):
210
- pod , container = location .name .split (":" )
211
- command = ["tar" , "chf" , "-" , "-C" , "/" , posixpath .relpath (src , "/" )]
212
- # noinspection PyUnresolvedReferences
213
- response = await self .client_ws .connect_get_namespaced_pod_exec (
214
- name = pod ,
215
- namespace = self .namespace or "default" ,
216
- container = container ,
217
- command = command ,
218
- stderr = True ,
219
- stdin = False ,
220
- stdout = True ,
221
- tty = False ,
222
- _preload_content = False ,
223
- )
224
- try :
225
- async with aiotarstream .open (
226
- stream = KubernetesResponseWrapper (response ),
227
- mode = "r" ,
228
- copybufsize = self .transferBufferSize ,
229
- ) as tar :
230
- await extract_tar_stream (tar , src , dst , self .transferBufferSize )
231
- except tarfile .TarError as e :
232
- raise WorkflowExecutionException (
233
- f"Error copying { src } from location { location } to { dst } : { e } "
234
- ) from e
235
- finally :
236
- await response .close ()
233
+ async with self ._get_stream_reader (location , src ) as reader :
234
+ try :
235
+ async with aiotarstream .open (
236
+ stream = reader ,
237
+ mode = "r" ,
238
+ copybufsize = self .transferBufferSize ,
239
+ ) as tar :
240
+ await extract_tar_stream (tar , src , dst , self .transferBufferSize )
241
+ except tarfile .TarError as e :
242
+ raise WorkflowExecutionException (
243
+ f"Error copying { src } from location { location } to { dst } : { e } "
244
+ ) from e
237
245
238
246
async def _copy_remote_to_remote (
239
247
self ,
@@ -277,9 +285,9 @@ async def _copy_remote_to_remote(
277
285
namespace = self .namespace or "default" ,
278
286
container = location .name .split (":" )[1 ],
279
287
command = write_command ,
280
- stderr = True ,
281
- stdin = False ,
282
- stdout = True ,
288
+ stderr = False ,
289
+ stdin = True ,
290
+ stdout = False ,
283
291
tty = False ,
284
292
_preload_content = False ,
285
293
),
@@ -383,9 +391,9 @@ def _get_stream_reader(self, location: Location, src: str) -> StreamWrapperConte
383
391
namespace = self .namespace or "default" ,
384
392
container = container ,
385
393
command = ["tar" , "chf" , "-" , "-C" , dirname , basename ],
386
- stderr = False ,
387
- stdin = True ,
388
- stdout = False ,
394
+ stderr = True ,
395
+ stdin = False ,
396
+ stdout = True ,
389
397
tty = False ,
390
398
_preload_content = False ,
391
399
),
@@ -565,20 +573,20 @@ def __init__(
565
573
self .stringValues : MutableSequence [str ] | None = stringValues
566
574
self .skipCrds : bool = skipCrds
567
575
self .registryConfig = (
568
- registryConfig
576
+ str ( Path ( registryConfig ). expanduser ())
569
577
if registryConfig is not None
570
578
else os .path .join (str (Path .home ()), ".config/helm/registry.json" )
571
579
)
572
580
self .releaseName : str = (
573
581
releaseName if releaseName is not None else f"release-{ uuid .uuid1 ()} "
574
582
)
575
583
self .repositoryCache = (
576
- repositoryCache
584
+ str ( Path ( repositoryCache ). expanduser ())
577
585
if repositoryCache is not None
578
586
else os .path .join (str (Path .home ()), ".cache/helm/repository" )
579
587
)
580
588
self .repositoryConfig = (
581
- repositoryConfig
589
+ str ( Path ( repositoryConfig ). expanduser ())
582
590
if repositoryConfig is not None
583
591
else os .path .join (str (Path .home ()), ".config/helm/repositories.yaml" )
584
592
)
@@ -589,7 +597,7 @@ def __init__(
589
597
self .chartVersion : str | None = chartVersion
590
598
self .wait : bool = wait
591
599
592
- def base_command (self ) -> str :
600
+ def _get_base_command (self ) -> str :
593
601
return "" .join (
594
602
[
595
603
"helm " ,
@@ -616,7 +624,7 @@ async def deploy(self, external: bool) -> None:
616
624
f"Helm { version } is not compatible with Helm3Connector"
617
625
)
618
626
# Deploy Helm charts
619
- deploy_command = self .base_command () + "" .join (
627
+ deploy_command = self ._get_base_command () + "" .join (
620
628
[
621
629
"install " ,
622
630
self .get_option ("atomic" , self .atomic ),
@@ -649,10 +657,14 @@ async def deploy(self, external: bool) -> None:
649
657
logger .debug (f"EXECUTING { deploy_command } " )
650
658
proc = await asyncio .create_subprocess_exec (
651
659
* shlex .split (deploy_command ),
652
- stderr = asyncio .subprocess .DEVNULL ,
653
- stdout = asyncio .subprocess .DEVNULL ,
660
+ stderr = asyncio .subprocess .STDOUT ,
661
+ stdout = asyncio .subprocess .PIPE ,
654
662
)
655
- await proc .wait ()
663
+ stdout , _ = await proc .communicate ()
664
+ if proc .returncode != 0 :
665
+ raise WorkflowExecutionException (
666
+ f"FAILED Deployment of { self .deployment_name } environment:\n \t { stdout .decode ().strip ()} "
667
+ )
656
668
657
669
@cachedmethod (lambda self : self .locationsCache )
658
670
async def get_available_locations (
@@ -698,7 +710,7 @@ def get_schema(cls) -> str:
698
710
async def undeploy (self , external : bool ) -> None :
699
711
if not external :
700
712
# Undeploy
701
- undeploy_command = self .base_command () + "" .join (
713
+ undeploy_command = self ._get_base_command () + "" .join (
702
714
[
703
715
"uninstall " ,
704
716
self .get_option ("keep-history" , self .keepHistory ),
@@ -709,7 +721,15 @@ async def undeploy(self, external: bool) -> None:
709
721
)
710
722
if logger .isEnabledFor (logging .DEBUG ):
711
723
logger .debug (f"EXECUTING { undeploy_command } " )
712
- proc = await asyncio .create_subprocess_exec (* shlex .split (undeploy_command ))
713
- await proc .wait ()
724
+ proc = await asyncio .create_subprocess_exec (
725
+ * shlex .split (undeploy_command ),
726
+ stderr = asyncio .subprocess .STDOUT ,
727
+ stdout = asyncio .subprocess .PIPE ,
728
+ )
729
+ stdout , _ = await proc .communicate ()
730
+ if proc .returncode != 0 :
731
+ raise WorkflowExecutionException (
732
+ f"FAILED Undeployment of { self .deployment_name } environment:\n \t { stdout .decode ().strip ()} "
733
+ )
714
734
# Close connections
715
735
await super ().undeploy (external )
0 commit comments