
    )"                        d Z ddlmZ ddlmZ ddlmZ ddl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mZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlZ G d de      Zd Z G d de      Z d Z!d Z"d Z#ejH                  	 	 	 	 	 d"d       Z% G d de      Z&d Z'd Z(d Z)d Z* ejV                  d      fdZ,d  Z-d! Z.y)#z1Functions for reading the skaffold events stream.    )absolute_import)division)print_function)unicode_literalsN)json_stream)config)log)
properties)console_attr)update_manager)filesc                       e Zd ZdZy)StopThreadErrorz-The thread has been stopped by a ThreadEvent.N)__name__
__module____qualname____doc__     /lib/googlecloudsdk/command_lib/code/skaffold.pyr   r   '   s    5r   r   c                     t               )zRaise a KeyboardInterrupt.)KeyboardInterrupt)unused_signumunused_stacks     r   _KeyboardInterruptHandlerr   -   s    r   c                   "    e Zd ZdZd Zd Zd Zy)_SigInterruptedHandlerz;Context manager to capture SIGINT and send it to a handler.c                      d | _         || _        y N)_orig_handler_handler)selfhandlers     r   __init__z_SigInterruptedHandler.__init__5   s    DDMr   c                     t        j                  t         j                        | _        t        j                   t         j                  | j                         y r   )signal	getsignalSIGINTr    r!   r"   s    r   	__enter__z _SigInterruptedHandler.__enter__9   s/    ))&--8D
MM&--/r   c                 `    t        j                   t         j                  | j                         y r   )r&   r(   r    )r"   exc_type	exc_valuetbs       r   __exit__z_SigInterruptedHandler.__exit__=   s    
MM&--!3!34r   Nr   r   r   r   r$   r*   r/   r   r   r   r   r   2   s    C05r   r   c                      t        j                         j                  r]t        j                  j                  dg      r=t        j                  j                  t        j                         j                  dd      S y )Nskaffoldbin)	r   Pathssdk_rootr   UpdateManagerEnsureInstalledAndRestartospathjoinr   r   r   _FindOrInstallSkaffoldComponentr;   A   sM    lln""<<j\J77<<//
CC	r   c                      t         j                  j                  j                  j	                         xs! t               xs t        j                  d      } | st        d      | S )z)Find the path to the skaffold executable.r2   zUnable to locate skaffold.)	r
   VALUEScodeskaffold_path_overrideGetr;   
file_utilsFindExecutableOnPathEnvironmentError)r2   s    r   _FindSkaffoldrD   H   s[     33779 2%'2%%j1  

7
88	/r   c                  f    t        j                  t        j                  t	               dg            S )zGet skaffold version string.version)sixensure_text
subprocesscheck_outputrD   r   r   r   
GetVersionrK   S   s#    	00-/91MN	OOr   c              #   0  K   t               dd| dg}|r	|d|z  gz  }|r	|d|z  gz  }|r|dgz  }|r	|d|z  gz  }t        t              5  t        j                  j                         }|r&|j                  d |j                         D               t        j                         j                  rKt        j                  |d	   t        j                  z   t        j                         j                  z         |d	<   	 t        j                  ||
      }| t&        j(                  j+                          t&        j,                  j+                          ddd       y# t         $ r# j#                          |j%                          Y pw xY w# 1 sw Y   yxY ww)a  Run skaffold and catch keyboard interrupts to kill the process.

  Args:
    skaffold_config: Path to skaffold configuration yaml file.
    context_name: Kubernetes context name.
    namespace: Kubernetes namespace name.
    env_vars: Additional environment variables with which to run skaffold.
    debug: If true, turn on debugging output.
    events_port: If set, turn on the events api and expose it on this port.

  Yields:
    The skaffold process.
  devz-fz--port-forwardz--kube-context=%sz--namespace=%sz-vdebugz--rpc-http-port=%sc              3   v   K   | ]1  \  }}t        j                  |      t        j                  |      f 3 y wr   )rG   
ensure_str).0namevalues      r   	<genexpr>zSkaffold.<locals>.<genexpr>~   s3      6$4[T5 ..&u(=>$4s   79PATH)envN)rD   r   r   r8   environcopyupdateitemsr   r4   r5   rG   rO   pathseprI   Popenr   	terminatewaitsysstdoutflushstderr)	skaffold_configcontext_name	namespaceenv_varsdebugevents_portcmdrU   ps	            r   Skaffoldrj   X   sa    ( 
%8HI#,.//Cy())C
I;C ;.//C 78 **//
C	jj 6$,NN$46 6||~NN3v;#;#)<<>#:#:$; <c&k


3C
(ag
 JJJJ) 98  kkmffh 98sC   AF
B0F
;E<F
	F)FF
FF

FFc                   "    e Zd ZdZd Zd Zd Zy)PrintUrlThreadContexta  Context manager that starts a thread that prints outs local urls.

  When entering the context, start a thread that watches the skaffold events
  stream api, find the portForward events, and prints out the local urls
  for a service. This will continue until the context is exited.
  c                     t        j                         | _        t        j                  t        ||| j                  f      | _        y)zInitialize PrintUrlThreadContext.

    Args:
      service_name: Name of the service.
      events_port: Port number of the skaffold events stream api.
    )targetargsN)	threadingEvent_stopThread	_PrintUrl_thread)r"   service_namerg   s      r   r$   zPrintUrlThreadContext.__init__   s5     "DJ##k4::FHDLr   c                 8    | j                   j                          y r   )ru   startr)   s    r   r*   zPrintUrlThreadContext.__enter__   s    LLr   c                 8    | j                   j                          y r   )rr   set)r"   ro   s     r   r/   zPrintUrlThreadContext.__exit__   s    JJNNr   Nr0   r   r   r   rl   rl      s    	Hr   rl   c                    	 t        j                  t        ||            5 }t        ||       D ]  }|j	                         r
 ddd       yt        j                         }dj                  |j                  d      d|z  |j                               }|j                  d       t        j                  j                  |j                  |d	              	 ddd       y# 1 sw Y   yxY w# t        $ r Y yw xY w)
a  Read the local url of a service from the event stream and print it.

  Read the event stream api and find the portForward events. Print the local
  url as determined from the portFoward events. This function will continuously
  listen to the event stream and print out all local urls until eitherthe event
  stream connection closes or the stop event is set.

  Args:
    service_name: Name of the service.
    events_port: Port number of the skaffold events stream api.
    stop: threading.Event event.
  Nz Service URL: {bold}{url}{normal}T)boldzhttp://localhost:%s/)r|   urlnormal   blue)color)
contextlibclosing_OpenEventStreamRetryGetServiceLocalPortis_setr   GetConsoleAttrformatGetFontCoder]   r	   statusPrintColorizer   )rv   rg   stopresponseportconmsgs          r   rt   rt      s    			1+268 
9<D%h=$;;=

9 
9 ))+077d+&-??$ 8 & 			!

c89 >
9 
9 
9 
 
s;   C- !C!C- BC!C- !C*&C- *C- -	C98C9c                 z    t         j                  j                  j                  j	                  t        |             S )z4Open a connection to the skaffold events api output.)rG   movesurllibrequesturlopen_GetEventsUrlrg   s    r   OpenEventsStreamr      s(    				!	!	)	)-*D	EEr   c              #   Z   K   t        |       D ]  }t        ||      s|d   d     yw)zGet the local port for a service.

  This function yields the new local port every time a new port forwarding
  connection is created.

  Args:
    response: urlopen response.
    service_name: Name of the service.

  Yields:
    Local port number.
  	portEvent	localPortN)ReadEventStream_IsPortEventForService)r   rv   events      r   r   r      s1      x(ee\2+{++ )s   ++c              #   z   K   t        j                  |       D ]  }t        |t              s|d   d   }| ! yw)zRead the events from the skaffold event stream.

  Args:
    response: urlopen response.

  Yields:
    Events from the JSON payloads.
  resultr   N)r   ReadJsonStream
isinstancedict)r   payloadr   s      r   r   r      s>      ++H5ggt$Hg&E
K	 6s   9;r   )secondsc                    |j                         s	 t        |       S t               # t        j                  j                  j
                  j                  $ r" |j                  |j                                Y nw xY w|j                         s}r)a  Open a connection to the skaffold events api output.

  This function retries opening the connection until opening is succesful or
  stop_event is set.

  Args:
    events_port: Port of the events api.
    stop_event: A threading.Event object.
    retry_interval: Interval for which to sleep between tries.

  Returns:
    urlopen response.
  Raises:
    StopThreadError: The stop_event was set before a connection was established.
  )
r   r   rG   r   r   errorURLErrorr]   total_secondsr   )rg   
stop_eventretry_intervals      r   r   r      sv    $ 6k** 	 99!!** 6oon22456 s   
' AA:9A:c                 L    dj                  t        j                  |             S )Nz(http://localhost:{events_port}/v1/eventsr   )r   rG   	text_typer   s    r   r   r     s&    	3	:	:--, 
; 
. .r   c                 J    | j                  di       j                  d      |k(  S )Nr   resourceName)get)r   rv   s     r   r   r     s#    	;	#	'	'	7<	GGr   )NNNFN)/r   
__future__r   r   r   r   r   datetimeos.pathr8   r&   rI   r^   rp   googlecloudsdk.command_lib.coder   googlecloudsdk.corer   r	   r
   googlecloudsdk.core.consoler   googlecloudsdk.core.updaterr   googlecloudsdk.core.utilr   rA   rG   BaseExceptionr   r   objectr   r;   rD   rK   contextmanagerrj   rl   rt   r   r   r   	timedeltar   r   r   r   r   r   <module>r      s    8 &  % '      
  7 & # * 4 6 8 
6m 6
5V 5P
 3 3lF 4BF
,$$ *<););A)F4.
Hr   