
    [je                     d   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 dZ!dZ"dZ# G d d          Z$ G d d          Z% G d d          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               zv4.channel.k8s.iozv5.channel.k8s.ioc                       e Zd Zd Zd ZdS )
_IgnoredIOc                     d S N )self_xs     X/var/www/FlaskApp/flask-venv/lib/python3.11/site-packages/kubernetes/stream/ws_client.pywritez_IgnoredIO.write0   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.getvalue3   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	 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                 F   d| _         i | _        t                      | _        d| _        || _        | j        sdnd| _        |r)| j        st                      nt                      | _	        nt                      | _	        t          |||          | _        t          | j        dd          | _        | j        s]| j        rV| j                                        }|r;|                                D ]&\  }}|                                dk    r	|| _         n'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.
        FN
   
subprotocolsec-websocket-protocolT)
_connected	_channelsset_closed_channelsr+   binarynewliner   r	   _allr   create_websocketsockgetattr
getheadersitemslower_returncode)	r   configurationurlheaderscapture_allr1   headers_dictkvs	            r   __init__zWSClient.__init__8   s"      ##';9ttE 	%*.+D


799DII"DI$]CAA	"49mTBB 	DI 	9//11L (..00  DAqwwyy$<<<+,( = r   r   c                     || j         v r|| j        vr| j        rdndS |                     |           || j        v r| j        |         S | j        rdndS )zLPeek a channel and return part of the input,
        empty string otherwise.r    timeout)r0   r.   r1   update)r   channelrF   s      r   peek_channelzWSClient.peek_channelV   sn     d+++t~0M0M+-332-G$$$dn$$>'**k)ssr)r   c                     || j         v r|| j        vr| j        rdndS || j        vr|                     ||          }n| j        |         }|| j        v r| j        |= |S )zRead data from a channel.r   rD   )r0   r.   r1   rI   )r   rH   rF   rets       r   read_channelzWSClient.read_channel`   sy    d+++t~0M0M+-332-$.((##GW55CC.)Cdn$$w'
r   Nc                    |t          d          }t          j                    }|                                 rt          j                    |z
  |k     r|| j        v r^| j        |         }| j        |v rH|                    | j                  }|d|         }||dz   d         }|r|| j        |<   n| j        |= |S || j        v r+|| j        v r| j        |         }| j        |= |S | j        rdnd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   r   rD   rE   )	floattimeis_openr.   r2   findr0   r1   rG   )r   rH   rF   startdataindexrK   s          r   readline_channelzWSClient.readline_channell   sw   ?EllG	llnn 	Au!4w!>!>$.((~g.<4'' IIdl33Evv,Ca>D 426w// N73J$///dn,,.1Cw/J"k1ssr1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chrr5   send)r   rH   rT   r1   rZ   channel_prefixpayloads          r   write_channelzWSClient.write_channel   s     :T$ZZ3?:'-C##43CW 	F _^WEEN 4'	wv.....r   c                     | j         t          k    rdS t          t          |g          }| j                            |t          j                   | j        	                    |           dS )z#Close a channel (v5 protocol only).NrY   )
r+   V5_CHANNEL_PROTOCOLbytesCLOSE_CHANNELr5   rb   r   r_   r0   add)r   rH   rT   s      r   close_channelzWSClient.close_channel   s`    222FmW-..	tD$6777!!'*****r   c                 :    |                      t          |          S )z$Same as peek_channel with channel=1.rE   )rI   STDOUT_CHANNELr   rF   s     r   peek_stdoutzWSClient.peek_stdout          AAAr   c                 :    |                      t          |          S )z$Same as read_channel with channel=1.rE   )rL   rm   rn   s     r   read_stdoutzWSClient.read_stdout   rp   r   c                 :    |                      t          |          S )z(Same as readline_channel with channel=1.rE   )rV   rm   rn   s     r   readline_stdoutzWSClient.readline_stdout       $$^W$EEEr   c                 :    |                      t          |          S )z$Same as peek_channel with channel=2.rE   )rI   STDERR_CHANNELrn   s     r   peek_stderrzWSClient.peek_stderr   rp   r   c                 :    |                      t          |          S )z$Same as read_channel with channel=2.rE   )rL   rw   rn   s     r   read_stderrzWSClient.read_stderr   rp   r   c                 :    |                      t          |          S )z(Same as readline_channel with channel=2.rE   )rV   rw   rn   s     r   readline_stderrzWSClient.readline_stderr   ru   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.
        )r3   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   rQ   zWSClient.is_open   s
    r   c                 <    |                      t          |           dS )z)The same as write_channel with channel=0.N)re   STDIN_CHANNEL)r   rT   s     r   write_stdinzWSClient.write_stdin   s    =$/////r   c                 h   |                                  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|          \  }}}|rI| j        
                    d          \  }}|t          j        k    r	d| _        dS |t          j        k    s|t          j        k    r|j        }t!          |          dk    r|d         }|t"          k    rG| j        t&          k    r7t!          |          dk    r"|d         }	| j                            |	           dS |dd         }| j        s|                    d	d
          }|r\|t0          t2          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   Tr   r   zutf-8replace)rQ   r5   	connectedr-   hasattrselectr   registerPOLLIN
unregisterrecv_data_framer   OPCODE_CLOSEr_   r`   rT   lenri   r+   rg   r0   rj   r1   decoderm   rw   r3   r   r.   )
r   rF   r   r_op_codeframerT   rH   
close_chans
             r   rG   zWSClient.update   sP   ||~~ 	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t99q=="1gG -//D4DH[4[4[IIMM*.q'Z!266zBBB8D; ?#{{7I>> <"~~&FFF !IOOD111"$.886:DN7333 N7333t;33333C!	< !	< != 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.rE   N)rP   rQ   rG   )r   rF   rS   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)rQ   r:   rL   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-   r5   close)r   kwargss     r   r   zWSClient.close&  s?      9 	&DIO%%f%%%%%	& 	&r   )F)r   r   )r#   r$   r%   rB   rI   rL   rV   re   rk   ro   rr   rt   rx   rz   r|   r   rQ   r   rG   r   propertyr   r   r   r   r   r'   r'   7   s              <* * * *
 
 
 
A A A A8/ / /+ + +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=< =< =< =<~	* 	* 	* 	* $ $ X$"& & & & &r   r'   c                       e Zd Zd ZddZdS )
WSResponsec                 "    || _         || _        d S r   )r   rT   )r   rT   r   s      r   rB   zWSResponse.__init__1  s    			r   Nc                     dS )z Returns a given response header.Nr   )r   namedefaults      r   	getheaderzWSResponse.getheader5  s    tr   r   )r#   r$   r%   rB   r   r   r   r   r   r   /  s7               r   r   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>J  s    A^A^A^PT#d))A^A^A^r   )r   targetTN)
	websocketlocal_ports	enumerate_Port	threadingThreadjoin_proxydaemonrS   )r   r   portsixport_numberproxys         r   rB   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   r   r!   s    r   r   zPortForward.connectedP  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.socketT  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.errorY  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   r[   int2byterH   r   
socketpairpython_SocketrT   r   )r   r   r   ss       r   rB   zPortForward._Port.__init__c  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   rB   z"PortForward._Port._Socket.__init__y  s    %r   c                 ,    t          | j        |          S r   )r6   r   )r   r   s     r   __getattr__z%PortForward._Port._Socket.__getattr__|  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.setsockopt  sD     F...7f>P3P3PF''w>>>>>r   N)r#   r$   r%   rB   r   r   r   r   r   r   r   x  sA        & & &3 3 3? ? ? ? ?r   r   N)r#   r$   r%   rB   r   r   r   r   r   r   b  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   rD   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   r   filenorT   r   r   r   r   r   r_   RuntimeErrorr[   byte2intr   r   r   r   OPCODE_PINGOPCODE_PONGr   
isinstancer5   ssl	SSLSocketpendingrecvcreate_framerH   formatrb   )r   channel_portschannel_initializedr   r   kubernetes_datarlistwlistlocal_all_closedr   wr   r5   r   rZ   r   rH   r   rT   sents                       r   r   zPortForward._proxy  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%   rB   r   r   r   r   r   r   r   r   r   r   r   r   9  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   )r<   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t          dt                     |                    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: %sr,   zsec-websocket-protocol: %szsec-websocket-protocol: ,zwss://)	cert_reqsca_certscheck_hostnamer  certfilekeyfileserver_hostname)ssloptskip_utf8_validationheader)r   r   rg   V4_CHANNEL_PROTOCOL
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)r;   r<   r=   r  ssl_optsr   connect_opts          r   r4   r4     s    F J?g--MM-0HHIII d+w662678 	9 	9 	9 	9 	9L9L9LNaNabccc
~~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_proxyr  )http_proxy_hosthttp_proxy_portzproxy-authorizationBasicr   :http_proxy_authr   )no_proxyrG   splitr   r   hostnamer   r$  r8   r  r   r   )	r(  r;   r<   r=   	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          |
d          S t          dd                    |
          z  d          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  r=   _request_timeout<   _preload_contentTr>   r1   F)r1   rE      )rT   r   z%srD   r   r   reasonN)r  getr'   r   r   r   r   	ExceptionKeyboardInterrupt
SystemExitr   r   )r;   _methodr<   r   r=   r7  r9  r>   r1   clientalles               r   websocket_callrE  >  sO   
 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 	D3s33334"''#,,#6sCCCC(*5 4 4 4!CFF33334s$   D *<D '&D E%E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`r=   r;  N)r=  r1  r   r   r   r   r  r4   r   r>  r?  r@  r   r   )r;   rA  r<   r   r  r   paramr   r   r   r=   r   rD  s                r   portforward_callrH  W  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  collectionsr   r   r   r   rP   r[   r   six.moves.urllib.parser   r   r   r   r	   r   r
   r   r   r   base64r   requests.utilsr   r   rm   rw   r   RESIZE_CHANNELri   r  rg   r   r'   r   r   r  r4   r%  rE  rH  r   r   r   <module>rP     sD   


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



      



  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) ) { { { { { { { {u& u& u& u& u& u& u& u&p       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   