11import json
22import time
3+ import six
4+ import ssl
35import aiohttp
46import asyncio
57import collections
1012from kubernetes .client import Configuration
1113from kubernetes .client .api import core_v1_api
1214from kubernetes .stream import stream
15+ from kubernetes .stream .ws_client import STDOUT_CHANNEL , STDERR_CHANNEL , ERROR_CHANNEL
1316
1417from channels .db import database_sync_to_async
1518from channels .exceptions import DenyConnection
@@ -85,25 +88,27 @@ async def connect(self):
8588 await super ().connect ()
8689 self .pod_id = self .scope ["url_route" ]["kwargs" ]["pod_id" ]
8790
88- async def send (self , data ):
91+ async def send (self , data , channel = STDOUT_CHANNEL ):
92+ channel_prefix = chr (channel )
8993 if data is None :
9094 return
9195 elif isinstance (data , bytes ):
92- await super ().send (bytes_data = data )
96+ channel_prefix = six .binary_type (channel_prefix , "ascii" )
97+ await super ().send (bytes_data = channel_prefix + data )
9398 elif isinstance (data , str ):
94- await super ().send (text_data = data )
99+ await super ().send (text_data = channel_prefix + data )
95100
96101 async def task (self ):
97102 deadline = time .time () + settings .DRYCC_APP_POD_EXEC_TIMEOUT
98103 while self .stream .is_open () and self .conneted and time .time () < deadline :
99- await sync_to_async ( self . stream . update )( 0.1 )
100- if self .stream .peek_stdout ():
101- data = self . stream . read_stdout ()
102- elif self .stream .peek_stderr () :
103- data = self .stream .read_stderr ( )
104- else :
105- data = None
106- await self . send ( data )
104+ try :
105+ await sync_to_async ( self .stream .update )( 0.1 )
106+ for channel in ( ERROR_CHANNEL , STDOUT_CHANNEL , STDERR_CHANNEL ):
107+ if channel in self .stream ._channels :
108+ data = self .stream .read_channel ( channel )
109+ await self . send ( data , channel )
110+ except ssl . SSLEOFError :
111+ break
107112 await self .close (code = 1000 )
108113
109114 async def disconnect (self , close_code ):
@@ -115,14 +120,9 @@ async def receive(self, text_data=None, bytes_data=None):
115120 if self .stream is None and text_data is not None :
116121 args = (self .kubernetes .connect_get_namespaced_pod_exec , self .pod_id , self .id )
117122 kwargs = json .loads (text_data )
118- kwargs .update ({"stderr" : True , "stdout" : True })
119- if kwargs ["stdin" ]:
120- kwargs .update ({"_preload_content" : False })
121- self .stream = stream (* args , ** kwargs )
122- asyncio .create_task (self .task ())
123- else :
124- await self .send (stream (* args , ** kwargs ))
125- await self .close (code = 1000 )
123+ kwargs .update ({"stderr" : True , "stdout" : True , "_preload_content" : False })
124+ self .stream = stream (* args , ** kwargs )
125+ asyncio .create_task (self .task ())
126126 elif self .stream is not None :
127127 data = text_data if text_data else bytes_data
128128 channel , data = ord (data [0 ]), data [1 :]
0 commit comments