
    !                         d dl m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
Z
d dlZd dlmZmZmZmZ d ZdZdZdZdZ G d	 d
      Z ej.                  ddg      Zd Zd Zy)    )ApiExceptionN)	WebSocketABNFenableTrace)	urlencode
quote_plusurlparse
urlunparse            c                       e Zd Z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d Zy)WSClientc                    t        d       g }d| _        i | _        d| _        |rd|v r|j	                  d|d   z         |rd|v r|j	                  d|d   z         n|j	                  d       |j                  d      r[|j                  rOt        j                  |j                  xs t        j                         d	}|j                  "|j                  |d<   ndt        j                  i}|j                  r|j                  |d<   |j                  r|j                  |d<   t!        |d      | _        | j"                  j%                  ||       d| _        y
)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 authorizationzauthorization: %szsec-websocket-protocolzsec-websocket-protocol: %sz)sec-websocket-protocol: v4.channel.k8s.iozwss://)	cert_reqsca_certsNcheck_hostnamer   certfilekeyfile)ssloptskip_utf8_validation)headerT)r   
_connected	_channels_allappend
startswith
verify_sslsslCERT_REQUIREDssl_ca_certcertifiwhereassert_hostname	CERT_NONE	cert_filekey_filer   sockconnect)selfconfigurationurlheadersr   ssl_optss         .lib/third_party/kubernetes/stream/ws_client.py__init__zWSClient.__init__%   sC    FDODNDI ?g-mm''/*BBC+w6mm0456 7 mm?@
~~hM$<$<((#//B7==?h 
	&	&	2%2%B%B!"s}}-h*44hz)22hyFDIIIc&)DO    c                 b    | j                  |       || j                  v r| j                  |   S y)zRPeek a channel and return part of the input,

        empty string otherwise.
    timeoutr   )updater   )r-   channelr7   s      r2   peek_channelzWSClient.peek_channelQ   s0    
 	KKK $.. ^^G$$r4   c                     || j                   vr| j                  ||      }n| j                   |   }|| j                   v r| j                   |= |S )zRead data from a channel.)r   r:   )r-   r9   r7   rets       r2   read_channelzWSClient.read_channel[   sK    dnn$gw/cNN7#c$.. 
..
!Jr4   Nc                    |t        d      }t        j                         }| j                         rt        j                         |z
  |k  r|| j                  v rS| j                  |   }d|v r@|j	                  d      }|d| }||dz   d }|r|| j                  |<   |S | j                  |= |S | j                  |t        j                         z
  |z          | j                         rt        j                         |z
  |k  ryyyy)zRead a line from a channel.Ninf
r   r6   )floattimeis_openr   findr8   )r-   r9   r7   startdataindexr<   s          r2   readline_channelzWSClient.readline_channele   s    egIIKE
,,.TYY[507:	DNN	"~~g&4<))D/%Ve#eaij!$&*DNN7# * w'*
kk7TYY[058k: ,,.TYY[507:.:.r4   c                 R    | j                   j                  t        |      |z          y)zWrite data to a channel.N)r+   sendchr)r-   r9   rF   s      r2   write_channelzWSClient.write_channelx   s    IINN3w<$&'r4   c                 0    | j                  t        |      S )z$Same as peek_channel with channel=1.r6   )r:   STDOUT_CHANNELr-   r7   s     r2   peek_stdoutzWSClient.peek_stdout|       ^W==r4   c                 0    | j                  t        |      S )z$Same as read_channel with channel=1.r6   )r=   rN   rO   s     r2   read_stdoutzWSClient.read_stdout   rQ   r4   c                 0    | j                  t        |      S )z(Same as readline_channel with channel=1.r6   )rH   rN   rO   s     r2   readline_stdoutzWSClient.readline_stdout          AAr4   c                 0    | j                  t        |      S )z$Same as peek_channel with channel=2.r6   )r:   STDERR_CHANNELrO   s     r2   peek_stderrzWSClient.peek_stderr   rQ   r4   c                 0    | j                  t        |      S )z$Same as read_channel with channel=2.r6   )r=   rX   rO   s     r2   read_stderrzWSClient.read_stderr   rQ   r4   c                 0    | j                  t        |      S )z(Same as readline_channel with channel=2.r6   )rH   rX   rO   s     r2   readline_stderrzWSClient.readline_stderr   rV   r4   c                 :    | j                   }d| _         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   r   )r-   outs     r2   read_allzWSClient.read_all   s      ))CDIDNJr4   c                     | j                   S )z&True if the connection is still alive.)r   )r-   s    r2   rC   zWSClient.is_open   s    ??r4   c                 0    | j                  t        |       y)z)The same as write_channel with channel=0.N)rL   STDIN_CHANNEL)r-   rF   s     r2   write_stdinzWSClient.write_stdin   s    }d+r4   c                    | j                         sy| j                  j                  sd| _        yt	        j                  | j                  j                  fdd|      \  }}}|r| j                  j                  d      \  }}|t        j                  k(  rd| _        y|t        j                  k(  s|t        j                  k(  r|j                  }t        j                  r|j                  dd      }t        |      dkD  rot        |d         }|dd }|rY|t         t"        fv r| xj$                  |z  c_        || j&                  vr|| j&                  |<   y| j&                  |xx   |z  cc<   yyyyy)	z@Update channel buffers with at most one complete frame of input.NF Tzutf-8replacer   r   )rC   r+   	connectedr   selectrecv_data_framer   OPCODE_CLOSEOPCODE_BINARYOPCODE_TEXTrF   sixPY3decodelenordrN   rX   r   r   )r-   r7   r_op_codeframerF   r9   s           r2   r8   zWSClient.update   s>   <<>99dommTYY^^-r2w?GAq!yy006ngu	D%%	%d(((Gt7G7G,Gzz77Wi0$t9q=QL'ab$>>:: ii4idnn,(,dnnW%nnW%-%  	 -H 	r4   c                    |rt        j                          }| j                         rrt        j                          |z
  |k  rW| j                  |t        j                          z
  |z          | j                         rt        j                          |z
  |k  rUyyyy| j                         r$| j                  d       | j                         r#yy)zpWait till connection is closed or timeout reached.

    Buffer any input
        received during this time.
    r6   N)rB   rC   r8   )r-   r7   rE   s      r2   run_foreverzWSClient.run_forever   s     iikeLLNtyy{U2W<Wtyy{2U:< LLNtyy{U2W<N<N LLND! LLNr4   c                 d    d| _         | j                  r | j                  j                  di | yy)z-
        close websocket connection.
        FNrf   )r   r+   close)r-   kwargss     r2   rz   zWSClient.close   s,     DOyydiioo r4   )r   )N)__name__
__module____qualname__r3   r:   r=   rH   rL   rP   rS   rU   rY   r[   r]   r`   rC   rd   r8   rx   rz   rf   r4   r2   r   r   #   sZ    *X;&(>>B>>B,.<" r4   r   
WSResponserF   c                     t        |       }t        |      }|j                  dk(  rd|d<   t        |      S |j                  dk(  rd|d<   t        |      S )Nhttpwsr   httpswss)r	   listschemer
   )r/   
parsed_urlpartss      r2   get_websocket_urlr      s]    }*
z
%& E!H 
E	 G#E!H	E	r4   c                 n   |d   }|j                  dd      }|j                  dd      }|j                  d      }g }|j                  di       D ]H  \  }}	|dk(  r+t        |	t              r|	D ]  }
|j                  ||
f        6|j                  ||	f       J |r|d	t	        |      z   z  }	 t        | t        |      |      }|s|S |j                  |
       t        ddj                  |j                               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. args and kwargs are the parameters of
    apiClient.request method.
  r   _request_timeout<   _preload_contentTr0   query_paramscommand?r6   z%sr   r   )statusreasonN)get
isinstancer   r   r   r   r   rx   r   joinr`   	ExceptionKeyboardInterrupt
SystemExitr   str)r.   argsr{   r/   r   r   r0   r   keyvaluer   clientes                r2   websocket_callr      s5    	Q#ZZ 2B7ZZ 2D9JJy!' ,JJ~r2jc5
iJud3'S'N+  3,' 3 3<(((C0m%6s%;WEFm
/0dRWWV__%67788
&
	3 0
aA
//0s   .D <D D4D//D4)kubernetes.client.restr   ri   r%   rB   collections	websocketr   r   r   rn   r"   six.moves.urllib.parser   r   r	   r
   rc   rN   rX   ERROR_CHANNELRESIZE_CHANNELr   
namedtupler   r   r   rf   r4   r2   <module>r      sp   " 0     2 2 
 
 N Nz  z z $[##L6(;
0r4   