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