
    Zi+\                     b   d dl Z d dlmZmZ d dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
Z
d dlZd dlZd dlmZmZmZ d dlmZmZ d dlmZmZmZmZ d dlmZ d dlmZ d ZdZd	Zd
ZdZ  G d d          Z! G d d          Z" ej#        ddg          Z$ G d d          Z%ddZ&ddZ'd Z(d Z)d Z*dS )    N)ApiExceptionApiValueError)	urlencodeurlparse
urlunparse)StringIOBytesIO)	WebSocketABNFenableTrace"WebSocketConnectionClosedException)urlsafe_b64decode)should_bypass_proxies            c                       e Zd Zd Zd ZdS )
_IgnoredIOc                     d S N )self_xs     V/root/projects/butler/venv/lib/python3.11/site-packages/kubernetes/stream/ws_client.pywritez_IgnoredIO.write,   s        c                      t          d          )Nz_Tried to read_all() from a WSClient configured to not capture. Did you mean `capture_all=True`?)	TypeErrorr   s    r   getvaluez_IgnoredIO.getvalue/   s    yzzzr   N)__name__
__module____qualname__r   r!   r   r   r   r   r   +   s7          { { { { {r   r   c                       e Zd ZddZddZddZddZd Zdd	Zdd
Z	ddZ
ddZddZddZd Zd Zd ZddZddZed             Zd ZdS )WSClientFc                    d| _         i | _        || _        | j        sdnd| _        |r)| j        st	                      nt                      | _        nt                      | _        t          |||          | _	        d| _         d| _
        dS )a2  A websocket client with support for channels.

            Exec command uses different channels for different streams. for
        example, 0 is stdin, 1 is stdout and 2 is stderr. Some other API calls
        like port forwarding can forward different pods' streams to different
        channels.
        F
   
TN)
_connected	_channelsbinarynewliner   r	   _allr   create_websocketsock_returncode)r   configurationurlheaderscapture_allr,   s         r   __init__zWSClient.__init__4   s      #';9ttE 	%*.+D


799DII"DI$]CAA	r   r   c                 ^    |                      |           || j        v r| j        |         S dS )zLPeek a channel and return part of the input,
        empty string otherwise.timeout )updater+   )r   channelr9   s      r   peek_channelzWSClient.peek_channelH   s7     	G$$$dn$$>'**rr   c                     || j         vr|                     ||          }n| j         |         }|| j         v r| j         |= |S )zRead data from a channel.)r+   r=   )r   r<   r9   rets       r   read_channelzWSClient.read_channelP   sN    $.((##GW55CC.)Cdn$$w'
r   Nc                 :   |t          d          }t          j                    }|                                 rt          j                    |z
  |k     r|| j        v r^| j        |         }| j        |v rH|                    | j                  }|d|         }||dz   d         }|r|| j        |<   n| j        |= |S |                     |t          j                    z
  |z              |                                 r t          j                    |z
  |k     dS dS dS dS )zRead a line from a channel.Ninfr   r8   )floattimeis_openr+   r-   findr;   )r   r<   r9   startdataindexr?   s          r   readline_channelzWSClient.readline_channelZ   s0   ?EllG	llnn 	Au!4w!>!>$.((~g.<4'' IIdl33Evv,Ca>D 426w// N73JKK49;;!6!>K@@@ llnn 	Au!4w!>!>!>!> 	A 	A!>!> 	A 	Ar   c                    t           j        ot          |          t           j        k    }|rt          j        nt          j        }t          |          }|rt          j        |d          }||z   }| j        	                    ||           dS )zWrite data to a channel.ascii)opcodeN)
sixPY3typebinary_typer   OPCODE_BINARYOPCODE_TEXTchrr0   send)r   r<   rH   r,   rM   channel_prefixpayloads          r   write_channelzWSClient.write_channelm   s     :T$ZZ3?:'-C##43CW 	F _^WEEN 4'	wv.....r   c                 :    |                      t          |          S )z$Same as peek_channel with channel=1.r8   )r=   STDOUT_CHANNELr   r9   s     r   peek_stdoutzWSClient.peek_stdoutz          AAAr   c                 :    |                      t          |          S )z$Same as read_channel with channel=1.r8   )r@   rZ   r[   s     r   read_stdoutzWSClient.read_stdout~   r]   r   c                 :    |                      t          |          S )z(Same as readline_channel with channel=1.r8   )rJ   rZ   r[   s     r   readline_stdoutzWSClient.readline_stdout       $$^W$EEEr   c                 :    |                      t          |          S )z$Same as peek_channel with channel=2.r8   )r=   STDERR_CHANNELr[   s     r   peek_stderrzWSClient.peek_stderr   r]   r   c                 :    |                      t          |          S )z$Same as read_channel with channel=2.r8   )r@   rd   r[   s     r   read_stderrzWSClient.read_stderr   r]   r   c                 :    |                      t          |          S )z(Same as readline_channel with channel=2.r8   )rJ   rd   r[   s     r   readline_stderrzWSClient.readline_stderr   rb   r   c                     | j                                         }| j                                         | _         i | _        |S )a  Return buffered data received on stdout and stderr channels.
        This is useful for non-interactive call where a set of command passed
        to the API call and their result is needed after the call is concluded.
        Should be called after run_forever() or update()

        TODO: Maybe we can process this and return a more meaningful map with
        channels mapped for each input.
        )r.   r!   	__class__r+   )r   outs     r   read_allzWSClient.read_all   s8     i  ""I''))	
r   c                     | j         S )z&True if the connection is still alive.)r*   r    s    r   rE   zWSClient.is_open   s
    r   c                 <    |                      t          |           dS )z)The same as write_channel with channel=0.N)rX   STDIN_CHANNEL)r   rH   s     r   write_stdinzWSClient.write_stdin   s    =$/////r   c                     |                                  sdS | j        j        s	d| _        dS t	          t
          d          ryt          j                    }|                    | j        j        t
          j                   ||dz  }|                    |          }|	                    | j        j                   n&t          j        | j        j        fdd|          \  }}}|r%| j        
                    d          \  }}|t          j        k    r	d| _        dS |t          j        k    s|t          j        k    r|j        }t           j        r| j        s|                    dd          }t)          |          d	k    r|d
         }t           j        r| j        st+          |          }|d	d         }|r\|t,          t.          fv r| j                            |           || j        vr|| j        |<   dS | j        |xx         |z  cc<   dS dS dS dS dS )z@Update channel buffers with at most one complete frame of input.NFpolli  r   Tzutf-8replacer   r   )rE   r0   	connectedr*   hasattrselectrs   registerPOLLIN
unregisterrecv_data_framer   OPCODE_CLOSErR   rS   rH   rN   rO   r,   decodelenordrZ   rd   r.   r   r+   )	r   r9   rs   r_op_codeframerH   r<   s	            r   r;   zWSClient.update   s'   ||~~ 	Fy" 	#DOF 66"" 		5;==DMM$).&-888"5 		'""AOODIN++++m"BG5 5GAq!  	<!Y66t<<NGU$+++"'D...'T=M2M2Mz7 ;4; ;;;w	::Dt99q=="1gGw /t{ /"%g,,8D <"~~&FFF !IOOD111"$.886:DN7333 N7333t;33333-	< 	<
 3N2M !=
< <r   c                    |rt          j                     }|                                 rwt          j                     |z
  |k     ra|                     |t          j                     z
  |z              |                                 rt          j                     |z
  |k     [dS dS dS dS |                                 r,|                     d           |                                 *dS dS )zfWait till connection is closed or timeout reached. Buffer any input
        received during this time.r8   N)rD   rE   r;   )r   r9   rG   s      r   run_foreverzWSClient.run_forever   s      	*IKKE,,.. ETY[[5%87%B%BWty{{%:U%BDDD ,,.. ETY[[5%87%B%B%B%B E E E E%B%B ,,.. *D))) ,,.. * * * * *r   c                 &   |                                  rdS | j        n|                     t                    }t	          j        |          }|d         dk    rd| _        n,t          |d         d         d         d                   | _        | j        S )zi
        The return code, A None value indicates that the process hasn't
        terminated yet.
        NstatusSuccessr   detailscausesmessage)rE   r1   r@   ERROR_CHANNELyaml	safe_loadint)r   errs     r   
returncodezWSClient.returncode   s     <<>> 
	$4'''66nS))x=I--'(D$$'*3y>(+CA+Fy+Q'R'RD$##r   c                 J    d| _         | j        r | j        j        di | dS dS )z-
        close websocket connection.
        FNr   )r*   r0   close)r   kwargss     r   r   zWSClient.close   s?      9 	&DIO%%f%%%%%	& 	&r   )F)r   r   )r"   r#   r$   r6   r=   r@   rJ   rX   r\   r_   ra   re   rg   ri   rm   rE   rq   r;   r   propertyr   r   r   r   r   r&   r&   3   s              (      A A A A&/ / /B B B BB B B BF F F FB B B BB B B BF F F F    0 0 02< 2< 2< 2<h	* 	* 	* 	* $ $ X$"& & & & &r   r&   
WSResponserH   c                   \    e Zd Zd Zed             Zd Zd Zd Z G d d          Z	d Z
d	S )
PortForwardc                 4   || _         i | _        t          |          D ]#\  }}|                     ||          | j        |<   $t	          j        dd                    d |D                       z  | j                  }d|_        |	                                 dS )a&  A websocket client with support for port forwarding.

        Port Forward command sends on 2 channels per port, a read/write
        data channel and a read only error channel. Both channels are sent an
        initial frame containing the port number that channel is associated with.
        z!Kubernetes port forward proxy: %sz, c                 ,    g | ]}t          |          S r   )str).0ports     r   
<listcomp>z(PortForward.__init__.<locals>.<listcomp>  s    A^A^A^PT#d))A^A^A^r   )nametargetTN)
	websocketlocal_ports	enumerate_Port	threadingThreadjoin_proxydaemonrG   )r   r   portsixport_numberproxys         r   r6   zPortForward.__init__  s     #(// 	H 	HOB,0JJr;,G,GD[))  4tyyA^A^X]A^A^A^7_7__;
 
 
 r   c                     | j         j        S r   )r   ru   r    s    r   ru   zPortForward.connected  s    ~''r   c                 V    || j         vrt          d          | j         |         j        S NzInvalid port number)r   
ValueErrorsocketr   r   s     r   r   zPortForward.socket  s0    d...2333,33r   c                 V    || j         vrt          d          | j         |         j        S r   )r   r   errorr   s     r   r   zPortForward.error$  s0    d...2333,22r   c                 p    | j                                         D ]}|j                                         d S r   )r   valuesr   r   )r   r   s     r   r   zPortForward.close)  sA    $++-- 	  	 DK	  	 r   c                   .    e Zd Zd Z G d d          ZdS )PortForward._Portc                     || _         t          j        |dz            | _        t	          j                    \  }| _        |                     |          | _        d| _        d | _	        d S )Nr   r   )
r   rN   int2byter<   r   
socketpairpython_SocketrH   r   )r   r   r   ss       r   r6   zPortForward._Port.__init__.  sZ    *D<Q//DL
 $.00NAt{ ,,q//DKDIDJJJr   c                        e Zd Zd Zd Zd ZdS )PortForward._Port._Socketc                     || _         d S r   )_socket)r   r   s     r   r6   z"PortForward._Port._Socket.__init__D  s    %r   c                 ,    t          | j        |          S r   )getattrr   )r   r   s     r   __getattr__z%PortForward._Port._Socket.__getattr__G  s    t|T222r   c                     |t           j        k    r|t           j        k    rd S | j                            |||           d S r   )r   IPPROTO_TCPTCP_NODELAYr   
setsockopt)r   leveloptnamevalues       r   r   z$PortForward._Port._Socket.setsockoptJ  sD     F...7f>P3P3PF''w>>>>>r   N)r"   r#   r$   r6   r   r   r   r   r   r   r   C  sA        & & &3 3 3? ? ? ? ?r   r   N)r"   r#   r$   r6   r   r   r   r   r   r   -  sK        	 	 	*	? 	? 	? 	? 	? 	? 	? 	? 	? 	?r   r   c                 (   g }g }i }| j                                         D ]z}|                    |           |                    d           |                    |           |                    d           |j                            d           |||j        <   {d}	 g }g }| j        j        r6|                    | j                   |r|                    | j                   d}| j                                         D ]}|j                                        dk    r| j        j        r>|                    |j                   |j        r|                    |j                   d}i|j        r|                    |j                   d}|j        	                                 |r)| j        j        r|s| j        	                                 d S t          j
        ||g           \  }	}
}|	D ]}|| j        k    rjd}|rc	 | j                            d          \  }}nG# t          $ r: | j                                         D ]}|j        	                                 Y  d S w xY w|t          j        k    rn|j        st          d          t!          j        |j                  }|t%          |          k    rt          d|z            ||         }||         rz|dz  rW|j        d|_        |xj        |j        d	d                                          z  c_        |j        	                                 n|xj        |j        d	d          z  c_        nt%          |j                  d
k    rt          d          t!          j        |j        d	d                   t!          j        |j        dd
                   dz  z   }||j        k    rt          d|z            d||<   n7|t          j        t          j        t          j        fvrt          d|z            t3          | j        j        t6          j                  r| j        j                                        sd}|cy||         }|j                                        dk    rs|j                            d          }|r>|t          j        |j         |z   t          j                  !                                z  }|j        	                                 |
D ]}|| j        k    r*| j        j        "                    |          }||d          }7||         }|j                                        dk    r3|j        "                    |j                  }|j        |d          |_        )NFTr   zUnexpected frame data sizezUnexpected channel number: %sr   r:   r   r   z*Unexpected initial channel frame data size   z3Unexpected port number in initial channel frame: %szUnexpected websocket opcode: %si   )#r   r   appendr   setblockingr   ru   filenorH   r   rw   r{   r   r   rR   RuntimeErrorrN   byte2intr~   r   r}   r   OPCODE_PINGOPCODE_PONGr|   
isinstancer0   ssl	SSLSocketpendingrecvcreate_framer<   formatrU   )r   channel_portschannel_initializedr   r   kubernetes_datarlistwlistlocal_all_closedr   wr   r0   r   rM   r   r<   r   rH   sents                       r   r   zPortForward._proxyR  s    $++-- 	, 	,D  &&&&&u---  &&&&&u---K##D)))'+K$$T	5EE~' 1T^,,," 1LL000#(//11 0 0;%%''2--~/ 
0T[1119 6!LL555+0((9 0!LL555/4,, K--/// )A o $$&&&mE5"55GAq! 20 204>))"G! $,#,0N,J,J4,P,PMFEEA # # #(,(8(?(?(A(A 4 4 $ 1 1 3 3 3 3"FFF# "T%777#(: Q&23O&P&P P&)l5:&>&>G&#m*<*<<<&23RU\3\&]&] ]#0#9D27; D#*Q; !@'+z'957
$(JJ%*QRR.2G2G2I2I$IJJ$(K$5$5$7$7$7$7$(IIABB$?III#&uz??a#7#7*6(T+& +& %& /2l5:ac?.K.Ks|\a\fghijgj\kOlOlorOr.s#.$2B#B#B*6(]`k(k+& +& %& @D 3G < <#D,<d>NPTPa+bbb"./PSY/Y"Z"ZZ *4>+> N N ,SWSaSfSnSnSpSp ,&+GI " $,L 't,D{))++r11#{//<< 0+t/@ $t 3 $ 20 0 %fhh'OO
 !K--/// 5 54>))>.33ODDD&5dee&<OO&t,D{))++r11#{//	::$(Idee$4	iT	5s   H  ?I$#I$N)r"   r#   r$   r6   r   ru   r   r   r   r   r   r   r   r   r   r     s          , ( ( X(4 4 4
3 3 3
     "? "? "? "? "? "? "? "?Jc5 c5 c5 c5 c5r   r   c                 |   t          |           }t          |          }|j        dk    rd|d<   n|j        dk    rd|d<   |rmg }|D ]T\  }}|dk    r2t          |t                    r|D ]}|                    ||f           =|                    ||f           U|rt          |          |d<   t          |          S )Nhttpwsr   httpswsscommandr   )r   listschemer   r   r   r   )r3   query_params
parsed_urlpartsquerykeyr   r   s           r   get_websocket_urlr     s    #JEF""a		g	%	%a 	(& 	+ 	+JCiJud$;$;$ 1 1GLL#w00001 c5\**** 	( ''E!Her   c                    t          d           g }|r"d|v r|                    d|d         z             |r#d|v r|                    d|d         z             n|                    d           |                    d          r@| j        r9t          j        | j        pt          j                    d}| j	        
| j	        |d	<   nd
t          j
        i}| j        r
| j        |d<   | j        r
| j        |d<   | j        r
| j        |d<   t          |d          }d|i}| j        s| j        rt#          || ||          } |j        |fi | |S )NFauthorizationzauthorization: %szsec-websocket-protocolzsec-websocket-protocol: %sz)sec-websocket-protocol: v4.channel.k8s.iozwss://)	cert_reqsca_certscheck_hostnamer   certfilekeyfileserver_hostname)ssloptskip_utf8_validationheader)r   r   
startswith
verify_sslr   CERT_REQUIREDssl_ca_certcertifiwhereassert_hostname	CERT_NONE	cert_filekey_filetls_server_namer
   r   proxy_headerswebsocket_proxycareconnect)r2   r3   r4   r   ssl_optsr   connect_opts          r   r/   r/     s    F J?g--MM-0HHIII C+w662678 	9 	9 	9 	9 	ABBB
~~h 0M$< 0*%1DW]__
 
 (4)6)FH%&/ 7,6 5+4$ D&3&C"#FFFI	6K  Tm9 T)+}c7SSIc))[)))r   c                 T   |j         r/|                     d|j                             d          i           |j        r6t	          |j                  }|                     |j        |j        d           |j        r|j                                        D ]\  }}|dk    r|	                    d          rs|                                d         }t          |                                                              d          }|                     d|d	         |d         fi           | S )
zc An internal function to be called in api-client when a websocket
        create is requested.
    http_no_proxy,)http_proxy_hosthttp_proxy_portzproxy-authorizationBasicr   :http_proxy_authr   )no_proxyr;   splitr   r   hostnamer   r  itemsr   r   r}   )	r  r2   r3   r4   	proxy_urlr   r   b64valueauths	            r   r  r    s/     S_m.D.J.J3.O.OQRRR g]011	y/AV_Vdeefff" M&4::<< 	M 	MIC+++0@0@0I0I+ ;;==+(2299;;AA#FF""$5Qa7I#KLLLr   c                    t          ||                    d                    }|                    d          }|                    dd          }|                    dd          }|                    dd          }|                    dd	          }	 t          | ||||
          }	|s|	S |	                    |           |	                                }
|rt          |
          S t          dd                    |
          z            S # t          t          t          f$ r#}t          dt          |                    d}~ww xY w)zAn internal function to be called in api-client when a websocket
    connection is required. method, url, and kwargs are the parameters of
    apiClient.request method.r   r4   _request_timeout<   _preload_contentTr5   r,   F)r,   r8   z%sr:   r   r   reasonN)r   getr&   r   rm   r   r   	ExceptionKeyboardInterrupt
SystemExitr   r   )r2   _methodr3   r   r4   r   r"  r5   r,   clientalles               r   websocket_callr-  	  sB   
 CN!;!;
<
<Cjj##Gzz"4b99zz"4d;;**]D11KZZ%((F4-g{6RRR 	M#3444oo 	3c??"dRWWS\\1222(*5 4 4 4!CFF33334s$   D
 *:D
 %$D
 
E!D??Ec                    |                     d          }g }|D ]\  }}|dk    r|                    d          D ]}	 t          |          }	n # t          $ r t	          d|z            w xY wd|	cxk     rdk     sn t	          d|z            |	|v rt	          d|z            |                    |	           |st	          d	          t          ||          }|                     d
          }
	 t          | ||
          }t          ||          S # t          t          t          f$ r#}t          dt          |                    d}~ww xY w)zAn internal function to be called in api-client when a websocket
    connection is required for port forwarding. args and kwargs are the
    parameters of apiClient.request method.r   r   r  zInvalid port number: %sr   i   z+Port number must be between 0 and 65536: %szDuplicate port numbers: %sz"Missing required parameter `ports`r4   r#  N)r%  r  r   r   r   r   r   r/   r   r&  r'  r(  r   r   )r2   r)  r3   r   r   r   paramr   r   r   r4   r   r,  s                r   portforward_callr0  "  s   
 ::n--LE$ * *uGC(( 	* 	*J"%d))KK! J J J'(AD(HIIIJK////%////'(UX\(\]]]%'''(Dt(KLLL[)))) B@AAA
C
.
.Cjj##G4$]CAA	9e,,,(*5 4 4 4!CFF33334s#   AA*2 D E*EEr   )+syskubernetes.client.restr   r   r  collectionsrw   r   r   r   rD   rN   r   six.moves.urllib.parser   r   r   r   r	   r   r
   r   r   r   base64r   requests.utilsr   rp   rZ   rd   r   RESIZE_CHANNELr   r&   
namedtupler   r   r   r/   r  r-  r0  r   r   r   <module>r9     s#   


 > > > > > > > >        



      



  C B B B B B B B B B ! ! ! ! ! ! ! ! V V V V V V V V V V V V $ $ $ $ $ $ 0 0 0 0 0 0{ { { { { { { {K& K& K& K& K& K& K& K&\ $[#L6(;;
q5 q5 q5 q5 q5 q5 q5 q5h   (( ( ( (T  &4 4 424 4 4 4 4r   