
    )8                        S r SSKJr  SSKJr  SSKJr  SSKrSSKrSSKrSSKrSSK	r	SSK
r
SSKrSSKrSSKJr  SSKJr  SSKJr  SS	KJr  SS
KJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKrSSKr\	R<                  " S5      r " S S\R@                  5      r! " S S\R@                  5      r" " S S\R@                  5      r# " S S\R@                  5      r$ " S S\R@                  5      r%S r&S r'S r(S r)S  r*S! r+S" r,S# r-S$ r.S% r/\R`                  S3S& j5       r1S' r2S( r3S) r4S* r5 " S+ S,\65      r7 " S- S.\Rp                  " \Rr                  5      5      r: " S/ S0\R@                  5      r;S1r<S2 r=g)4z7Utility functions for gcloud emulators datastore group.    )absolute_import)division)unicode_literalsN)config)
exceptions)log)
properties)yaml)resource_printer)local_state)update_manager)encoding)files)	platformsz\[(.*)\]:(\d*)c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )NoCloudSDKError0   z(The module was unable to find Cloud SDK.c                 ,   > [         [        U ]  S5        g )Nz(Unable to find a Cloud SDK installation.)superr   __init__self	__class__s    0lib/googlecloudsdk/command_lib/emulators/util.pyr   NoCloudSDKError.__init__3   s    	/4)24     __name__
__module____qualname____firstlineno____doc__r   __static_attributes____classcell__r   s   @r   r   r   0   s    04 4r   r   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )NoEnvYamlError8   zUnable to find a env.yaml file.c                 J   > [         [        U ]  SR                  U5      5        g )NzgUnable to find env.yaml in the data_dir [{0}]. Please ensure you have started the appropriate emulator.)r   r(   r   format)r   data_dirr   s     r   r   NoEnvYamlError.__init__;   s!    	.$(	--3VH-=?r   r   r   r&   s   @r   r(   r(   8   s    '? ?r   r(   c                       \ rS rSrSrg)MissingProxyErrorA   r   Nr   r    r!   r"   r$   r   r   r   r/   r/   A       r   r/   c                       \ rS rSrSrg)NoEmulatorErrorE   r   Nr1   r   r   r   r4   r4   E   r2   r   r4   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )InvalidHostErrorI   z$The configured host:port is invalid.c                 ,   > [         [        U ]  S5        g )NzeEmulator host-port must take the form ADDRESS:PORT where ADDRESS is a hostname, IPv4 or IPv6 address.)r   r7   r   r   s    r   r   InvalidHostError.__init__L   s    	
D*	01r   r   r   r&   s   @r   r7   r7   I   s    ,1 1r   r7   c                     SR                  X5      n [        R                  R                  U /US9  g! [        R
                   a    [        5       ef = f)zEnsures that the specified component is installed.

Args:
  component_id: str, the name of the component
  for_text: str, the text explaining what the component is necessary for

Raises:
  NoCloudSDKError: If a Cloud SDK installation is not found.
z,You need the [{0}] component to use the {1}.)msgN)r+   r   UpdateManagerEnsureInstalledAndRestartr   InvalidSDKRootErrorr   )component_idfor_textr<   s      r   EnsureComponentIsInstalledrB   R   sZ     
8
&
(   ::L>?B ; D		(	( 

s	   3 Ac                      [         R                  " 5       R                  n U (       d
  [        5       e[        R
                  " SU 5        U $ )zGets the directory of the root of the Cloud SDK, error if it doesn't exist.

Raises:
  NoCloudSDKError: If there is no SDK root.

Returns:
  str, The path to the root of the Cloud SDK.
zFound Cloud SDK root: %s)r   Pathssdk_rootr   r   debug)rE   s    r   GetCloudSDKRootrG   e   s5     \\^$$(	

))&1	/r   c                     [         R                  R                  US5      n[        R                  " U5       n[
        R                  " U /SUS9  SSS5        g! , (       d  f       g= f)zWrites the given environment values into the output_dir/env.yaml file.

Args:
  env: {str: str}, Dictonary of environment values.
  output_dir: str, Path of directory to which env.yaml file should be written.
env.yamlr
   )print_formatoutN)ospathjoinr   
FileWriterr   Print)env
output_direnv_file_pathenv_files       r   WriteEnvYamlrU   u   sH     '',,z:6-&(C5v8D '&&s   A
A&c                    [         R                  R                  U S5      n [        R                  " U5       n[
        R                  " U5      sSSS5        $ ! , (       d  f       g= f! [        R                   a    [        U 5      ef = f)zReads and returns the environment values in output_dir/env.yaml file.

Args:
  output_dir: str, Path of directory containing the env.yaml to be read.

Returns:
  env: {str: str}
rI   N)	rL   rM   rN   r   
FileReaderr
   loadMissingFileErrorr(   )rR   rS   fs      r   ReadEnvYamlr[      sc     '',,z:6-%			-	(AYYq\ 
)	(	(			 %

$$%s(   A) A	A) 
A&"A) &A) ) B	c           	      4   [         R                  R                  5       nSnU[         R                  R                  L a  Sn[        R
                  " U 5       H?  u  p4SU;   a  SR                  US9n[        R                  " SR                  UUUS95        MA     g)	zPrint OS specific export commands for the given environment values.

Args:
  env: {str: str}, Dictonary of environment values.
exportset z	"{value}")valuez{export_command} {var}={value})export_commandvarr`   N)	r   OperatingSystemCurrentWINDOWSsix	iteritemsr+   r   rP   )rQ   
current_osra   rb   r`   s        r   PrintEnvExportri      s     ((002*.9,,444NMM#&jc
e|  u -eII.55% 6   'r   c                    [         R                  R                  5       nSnU[         R                  R                  L a  Sn[        R
                  " U 5       H&  n[        R                  " UR                  US95        M(     g)zPrint OS specific unset commands for the given environment variables.

Args:
  env: {str: str}, Dictionary of environment values, the value is ignored.
zunset {var}z
set {var}=)rb   N)	r   rc   rd   re   rf   iterkeysr   rP   r+   )rQ   rh   ra   rb   s       r   PrintEnvUnsetrl      sc     ((002* .9,,444!N\\#cIIn###,- r   c                     [        U S5      nU(       a  U$ [        R                  " 5       R                  n[        R
                  R                  USU 5      n[        R                  " U5        U$ )zIf present, returns the configured data dir, else returns the default.

Args:
  prefix: pubsub, datastore, bigtable, etc. The prefix for the *_data_dir
  property of the emulators section.

Returns:
  str, The configured or default data_dir path.
r,   	emulators)	_GetEmulatorPropertyr   rD   global_config_dirrL   rM   rN   r   MakeDir)prefix
configuredconfig_rootdefault_data_dirs       r   
GetDataDirrv      sS     $FJ7*
"00+WW\\+{FC-- !	r   c                    [         R                  (       a  SOSnSR                  U[        R                  " SS5      S9n[        U S5      =(       d    Un [        U5      u  pE[        R                  U5      (       a  [         R                  O[         R                  n[         R                   " U[         R                  5      n[        U5      nUR                  XE45      S:w  a  U$ U$ ! [         a    [        5       ef = f)	aG  If present, returns the configured host port, else returns the default.

Args:
  prefix: str, The prefix for the *-emulator property group to look up.

Raises:
  InvalidHostError: If configured host-port is not of the form
  ADDRESS:PORT.

Returns:
  str, Configured or default host_port if present, else an unused local port.
z[::1]	localhostz{host}:{port}i@  i'#  )hostport	host_portr   )sockethas_ipv6r+   randomrandintro   _ParseHostPort_IPV6_REmatchAF_INET6AF_INETSOCK_STREAMint
ValueErrorr7   
connect_ex)rr   default_hostarbitrary_host_portrs   ry   rz   protocolsocks           r   GetHostPortr      s     #OO, (..fnnT48 / :#FK8O<O*
+JD"*.."<"<v&..H==6#5#56Dt9D 
__d\"a'	 
 

s   A7C& &C;c                     [         R                  U 5      (       a#  [         R                  U 5      R                  5       $ U R                  S5      $ )N:)r   r   groupssplit)hostports    r   r   r      s8    ^^H>>(#**,,>>#r   c                     SnSR                  X5      n[        R                   HL  nUR                  U:X  d  M  UR	                  U5      (       d  M-  UR                  U5      R                  5       s  $    g)a!  Returns the value of the given property in the given emulator group.

Args:
  prefix: str, The prefix for the *_emulator property group to look up.
  prop_name: str, The name of the property to look up.

Returns:
  str, The the value of the given property in the specified emulator group.
emulatorz{}_{}N)r+   r	   VALUESnameHasPropertyPropertyGet)rr   	prop_nameproperty_group	full_namesections        r   ro   ro      sb     .nnV/)""g||~%'*=*=i*H*Hi(,,.. # 
r   c              #   0  #    U=(       d    [         R                  n[        R                  R	                  5       (       dD  [
        R                  " S5      [
        R                  " 5       :w  a  [
        R                  " SS5        [         R                  " U U[         R                  S9n Uv   UR                  5       c!  UR                  5         UR                  5         gg! UR                  5       c!  UR                  5         UR                  5         f f = f7f)a/  Starts subprocess with given args and ensures its termination upon exit.

This starts a subprocess with the given args. The stdout and stderr of the
subprocess are piped. Note that this is a context manager, to ensure that
processes (and references to them) are not leaked.

Args:
  args: [str], The arguments to execute. The first argument is the command.
  log_file: optional file argument to reroute process's output. If given,
    will be closed when the file is terminated.

Yields:
  process, The process handle of the subprocess that has been started.
r   )stdoutstderrN)
subprocessPIPEr   rc   	IsWindowsrL   getsidgetpidsetpgidPopenSTDOUTpoll	terminatewait)argslog_filereroute_stdoutprocesss       r   Execr      s       .z.		"	"	,	,	.	.	yy|ryy{"jjAT$2$.$5$57'
M||~lln w||~lln s   B%D(C ,3D4DDc           	      l   U R                   R                  5       nU(       a  [        R                  R	                  SR                  U[        R                  " UR                  5       5      5      5        [        R                  R                  5         U R                   R                  5       nU(       a  M  gg)zPrepends the given prefix to each line of the given process's output.

Args:
  process: process, The handle to the process whose output should be prefixed
  prefix: str, The prefix to be prepended to the process's output.
z	[{0}] {1}N)
r   readliner   statusrP   r+   r   Decoderstripflush)r   rr   output_lines      r   PrefixOutputr      sz     '')+JJ[''(08J8J8L(MO PJJ..))+K	 	r   c                    / nU R                   (       a  [        R                  U R                   R                  5      (       a&  SR	                  U R                   R                  5      nOU R                   R                  nU R                   R                  b   UR                  SR	                  U5      5        U R                   R                  b4  UR                  SR	                  U R                   R                  5      5        U$ )z8Converts an argparse.Namespace to a list of arg strings.z[{}]z
--host={0}z
--port={0})r{   r   r   ry   r+   appendrz   )r   	args_listry   s      r   BuildArgsListr   /  s    )	^^~~dnn))**]]4>>../d^^  d~~&|**401~~&|**4>>+>+>?@	r   c                     [         R                  R                  [        5       SSR	                  U 5      5      n[         R                  R                  U5      (       d  [        SR	                  U 5      5      eU$ )Nplatformz{0}-emulatorzNo {0} directory found.)rL   rM   rN   rG   r+   isdirr4   )r   emulator_dirs     r   GetEmulatorRootr   ?  sZ    o/(.*?*?*IK,	|	$	$
3::8D
EE	r   c                      [         R                  R                  [        5       SS5      n [         R                  R	                  U 5      (       d  [        S5      eU $ )z+Returns path to the emulator reverse proxy.r   zemulator-reverse-proxyzremulator-reverse-proxy component must be installed. try running `gcloud components install emulator-reverse-proxy`)rL   rM   rN   rG   r   r/   )rM   s    r   GetEmulatorProxyPathr   G  sJ    	o'5M	N$	t		
 	=> > 
+r   c                   <   ^  \ rS rSrSrSS jrS rU 4S jrSrU =r	$ )AttrDictiU  zAllows for a wrapped map to be indexed via attributes instead of keys.

Example:
m = {'a':'b', 'c':{'d':'e', 'f':'g'}}
a = AttrDict(m)
m['c']['d'] == a.c.d
c                     U(       aN  0 n[         R                  " U5       H+  u  pEUn[        U[        5      (       a  [	        XR5      nXcU'   M-     X0l        OXl        X l        g)zInitializes attributes dictionary.

Args:
  _dict: dict, the map to convert into an attribute dictionary
  recurse: bool, if True then any nested maps will also be treated as
           attribute dictionaries
N)rf   rg   
isinstancedictr   _dict_recurse)r   r   recurse	dict_copykeyr`   tosets          r   r   AttrDict.__init__^  sU     ie,*#eT""5*%#	 -
 jjMr   c                      U R                   U   $ N)r   )r   attrs     r   __getattr__AttrDict.__getattr__r  s    ::dr   c                 l   > U[        SS/5      ;   a  [        [        U ]  X5        g X R                  U'   g )Nr   r   )r^   r   r   __setattr__r   )r   r   r`   r   s      r   r   AttrDict.__setattr__u  s0    sGZ())Hd'4jjr   )r   r   )T)
r   r    r!   r"   r#   r   r   r   r$   r%   r&   s   @r   r   r   U  s    ( r   r   c                       \ rS rSrSr\R                  S 5       r\\R                  S 5       5       r
\\R                  S 5       5       r\\R                  S 5       5       r\\R                  S 5       5       rS rS	rg
)Emulatori|  z5This organizes the information to expose an emulator.c                     [        5       e)zStarts the emulator process on the given port.

Args:
  port: int, port number for emulator to bind to

Returns:
  subprocess.Popen, the emulator process
NotImplementedError)r   rz   s     r   StartEmulator.Start       
r   c                     [        5       e)zcReturns the grpc route prefixes to route to this service.

Returns:
  list(str), list of prefixes.
r   r   s    r   prefixesEmulator.prefixes       
r   c                     [        5       e)zReturns the service name this emulator corresponds to.

Note that it is assume that the production API this service is emulating
exists at <name>.googleapis.com

Returns:
  str, the service name
r   r   s    r   service_nameEmulator.service_name  s     
r   c                     [        5       e)zvReturns title of the emulator.

This is just for nice rendering in the cloud sdk.

Returns:
  str, the emulator title
r   r   s    r   emulator_titleEmulator.emulator_title  r   r   c                     [        5       e)zRReturns cloud sdk component to install.

Returns:
  str, cloud sdk component name
r   r   s    r   emulator_componentEmulator.emulator_component  r   r   c                     [         R                  " 5       u  p[        R                  R	                  SR                  U R                  U5      5        U$ )a  Returns the OS-level handle to log file.

This handle is the same as would be returned by os.open(). This is what the
subprocess interface expects. Note that the caller needs to make sure to
close this to avoid leaking file descriptors.

Returns:
  int, OS-level handle to log file
zLogging {0} to: {1})tempfilemkstempr   r   rP   r+   r   )r   log_file_nor   s      r   	_GetLogNoEmulator._GetLogNo  sA     %,,.KJJ*11$2C2CXNOr   r   N)r   r    r!   r"   r#   abcabstractmethodr   propertyabstractpropertyr   r   r   r   r   r$   r   r   r   r   r   |  s    = 	  	       	   	           r   r   c                       \ rS rSrSrSrg)EmulatorArgumentsErrori  z$Generic error for invalid arguments.r   N)r   r    r!   r"   r#   r$   r   r   r   r   r     s    ,r   r   iò  c                      [         R                  " [        5      (       a  [        $ [        SR	                  [        5      5      e)z~Returns default port if available.

Raises:
  EmulatorArgumentsError: if port is not available.

Returns:
  int, default port
z,Default emulator port [{}] is already in use)
portpickeris_port_free_DEFAULT_PORTr   r+   r   r   r   DefaultPortIfAvailabler     s8     ]++
 6==mLN Nr   r   )>r#   
__future__r   r   r   r   
contextlibrL   r~   rer|   r   r   googlecloudsdk.corer   r   r   r	   r
   googlecloudsdk.core.resourcer   googlecloudsdk.core.updaterr   r   googlecloudsdk.core.utilr   r   r   r   rf   compiler   Errorr   r(   r/   r4   r7   rB   rG   rU   r[   ri   rl   rv   r   r   ro   contextmanagerr   r   r   r   r   objectr   with_metaclassABCMetar   r   r   r   r   r   r   <module>r     si   > &  ' 
  	  	    & * # * $ 9 3 6 - * .  
 ::'(4j&& 4?Z%% ?
(( j&& 1z'' 1& 	E%"&.&B$  >, $v $NMs!!#++. M`Z-- 
 Nr   