
    \                        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	J
r
  SSK	Jr  SSKJr  SS	KJr  SS
KJr  Sr\4rSrSrSrSr " S S\R0                  5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r\" 5       r " S S\5      r  " S S\5      r! " S  S!\5      r"S" r#S# r$S$ r%S% r&S& r'S' r(S( r)S) r*S*r+S+ r,g),z;Support functions for the handling of named configurations.    )absolute_import)division)unicode_literalsN)config)
exceptions)properties_file)encoding)filesNONEdefaultz^[a-z][-a-z0-9]*$config_z^config_([a-z][-a-z0-9]*)$c                       \ rS rSrSrSrg)Error+   z4Base class for errors handling named configurations. N__name__
__module____qualname____firstlineno____doc____static_attributes__r       7lib/googlecloudsdk/core/configurations/named_configs.pyr   r   +   s    <r   r   c                       \ rS rSrSrSrg)NamedConfigError/   z6Errors when dealing with operations on configurations.r   Nr   r   r   r   r   r   /   s    >r   r   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )NamedConfigFileAccessError3   z1Raise for errors dealing with file access errors.c           
      b   > [         [        U ]  SR                  U[	        USU5      5      5        g )Nz
{0}.
  {1}strerror)superr   __init__formatgetattr)selfmessageexc	__class__s      r   r$   #NamedConfigFileAccessError.__init__6   s.    	
$d4]5I5Ij#.60 1r   r   r   r   r   r   r   r$   r   __classcell__r*   s   @r   r   r   3   s    91 1r   r   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )InvalidConfigName;   z/Raise to indicate an invalid named config name.c                 r   > [         [        U ]  SR                  USR	                  [
        5      5      5        g )NzInvalid name [{0}] for a configuration.  Except for special cases ({1}), configuration names start with a lower case letter and contain only lower case letters a-z, digits 0-9, and hyphens '-'.,)r#   r0   r$   r%   join_RESERVED_CONFIG_NAMES)r'   bad_namer*   s     r   r$   InvalidConfigName.__init__>   s1    	
T+	 $VHchh7M.NO	Qr   r   r,   r.   s   @r   r0   r0   ;   s    7Q Qr   r0   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )ReadOnlyConfigurationErrorF   zAAn exception for when the active config is read-only (e.g. None).c                 J   > [         [        U ]  SR                  U5      5        g )Nz0Properties in configuration [{0}] cannot be set.)r#   r9   r$   r%   )r'   config_namer*   s     r   r$   #ReadOnlyConfigurationError.__init__I   s"    	
$d4:AA+NPr   r   r,   r.   s   @r   r9   r9   F   s    IP Pr   r9   c                   F    \ rS rSrSrS rS rS rS rS r	\
S 5       rS	rg
)_FlagOverrideStackN   a\  Class representing a stack of configuration flag values or `None`s.

Each time a command line is parsed (the original, and any from commands
calling other commands internally), the new value for the --configuration
flag is added to the top of the stack (if it is provided).  This is used for
resolving the currently active configuration.

We need to do quick parsing of the args here because things like logging are
used before argparse parses the command line and logging needs properties.
We scan the command line for the --configuration flag to get the active
configuration before any of that starts.
c                     / U l         g N_stackr'   s    r   r$   _FlagOverrideStack.__init__\   s	    DKr   c                     U R                  5       nU R                  R                  U5        X!:w  a  [        R	                  5         gg)z(Add a new value to the top of the stack.N)ActiveConfigrD   appendActivePropertiesFile
Invalidate)r'   config_flagold_flags      r   Push_FlagOverrideStack.Push_   s9      "HKK{#%%' r   c                 L    U R                  [        R                  U5      5        g)zParse the args and add the value that was found to the top of the stack.

Args:
  args: [str], The command line args for this invocation.
N)rN   r?   _FindFlagValue)r'   argss     r   PushFromArgs_FlagOverrideStack.PushFromArgsf   s     	II //56r   c                 6    U R                   R                  5       $ )z$Remove the top value from the stack.)rD   poprE   s    r   Pop_FlagOverrideStack.Popn   s    ;;??r   c                 R    [        U R                  5       H  nU(       d  M  Us  $    g)z$Get the top most value on the stack.N)reversedrD   )r'   values     r   rH   _FlagOverrideStack.ActiveConfigr   s$    $++&	 ' r   c                     SnUS-   nSnSn[        U5       H<  nXb:X  a  Un  U$ UR                  U5      (       a  UR                  SS5      u  pu  U$ UnM>     U$ )zParse the given args to find the value of the --configuration flag.

Args:
  args: [str], The arguments from the command line to parse

Returns:
  str, The value of the --configuration flag or None if not found.
z--configuration=N   )rZ   
startswithsplit)clsrR   flagflag_eq	successorrL   arg_s           r   rQ   !_FlagOverrideStack._FindFlagValuey   s~     DSjGIK ~	  
	 	 3*  i  r   rC   N)r   r   r   r   r   r$   rN   rS   rW   rH   classmethodrQ   r   r   r   r   r?   r?   N   s4    (7  r   r?   c                   |    \ rS rSrSr\S 5       r\SS j5       r\S 5       r\S 5       r	\S 5       r
\S 5       rS	rg
)ConfigurationStore   zEClass for performing low level operations on configs and their files.c                      [        SS9$ )am  Gets the currently active configuration.

There must always be an active configuration.  If there isn't this means
no configurations have been created yet and this will auto-create a default
configuration.  If there are legacy user properties, they will be migrated
to the newly created configuration.

Returns:
  Configuration, the currently active configuration.
Tforce_create)rH   r   r   r   rH   ConfigurationStore.ActiveConfig   s     T**r   c                 J   [         R                  " 5       R                  n[        R	                  5       nUR
                  n0 nU (       a  [        [        [        U:H  5      U[        '    [        R                  " U5      nU HH  n[        R                  " [        U5      nU(       d  M'  UR                  S5      n[        XU:H  5      XH'   MJ     U$ ! [        [        4 aD  n	U	R                   [         R"                  :w  a  [%        SR'                  U5      U	5      e Sn	A	0 $ Sn	A	ff = f)a  Returns all the configurations that exist.

This determines the currently active configuration so as a side effect it
will create the default configuration if no configurations exist.

Args:
  include_none_config: bool, True to include the NONE configuration in the
    list. This is a reserved configuration that indicates to not use any
    configuration.  It is not explicitly created but is always available.

Returns:
  {str, Configuration}, A map of configuration name to the configuration
  object.
r_   z4List of configurations could not be read from: [{0}]N)r   Pathsnamed_config_directoryrk   rH   nameConfiguration_NO_ACTIVE_CONFIG_NAMEoslistdirrematch_CONFIG_FILE_REGEXgroupOSErrorIOErrorerrnoENOENTr   r%   )
include_none_config
config_diractive_configactive_config_nameconfigsconfig_filesfmrt   r)   s
             r   
AllConfigsConfigurationStore.AllConfigs   s      66J&335M&++G(5
 "8<N"N)Pg$%"ZZ
+l!HH'+1$'6H.HI'-	 
 nW "	ell	"(BII " 	" 
# I"s   (;C '&C D"9DD"c                    [        U SS9  [        R                  " 5       n[        X5      n[        R
                  R                  U5      (       a  [        SR                  U 5      5      e [        R                  " UR                  5        [        R                  " US5        [        U SS9$ ! [        R                   a+  n[        SR                  U UR                  5      U5      eSnAff = f)aR  Creates a configuration with the given name.

Args:
  config_name: str, The name of the configuration to create.

Returns:
  Configuration, The configuration that was just created.

Raises:
  NamedConfigError: If the configuration already exists.
  NamedConfigFileAccessError: If there a problem manipulating the
    configuration files.
Fallow_reservedz5Cannot create configuration [{0}], it already exists. zWFailed to create configuration [{0}].  Ensure you have the correct permissions on [{1}]N)	is_active)_EnsureValidConfigNamer   rr   _FileForConfigrw   pathexistsr   r%   
file_utilsMakeDirrs   WriteFileContentsr   r   ru   r<   paths	file_pathes       r   CreateConfigConfigurationStore.CreateConfig   s     ;u=LLNE{2I	ww~~i  
A6+   J556""9b1 66  J&!!'(-(D(D"FGHJ JJs   *7B+ +C*?&C%%C*c                    [        U SS9  [        R                  " 5       n[        X5      n[        R
                  R                  U5      (       d  [        SR                  U 5      5      eU [        5       :X  a  [        SR                  U 5      5      eU [        5       :X  a  [        SR                  U 5      5      e [        R                  " U5        g! [        [        4 a+  n[        SR                  U UR                  5      U5      eSnAff = f)a  Creates the given configuration.

Args:
  config_name: str, The name of the configuration to delete.

Raises:
  NamedConfigError: If the configuration does not exist.
  NamedConfigFileAccessError: If there a problem manipulating the
    configuration files.
Fr   z5Cannot delete configuration [{0}], it does not exist.zLCannot delete configuration [{0}], it is the currently active configuration.zmCannot delete configuration [{0}], it is currently set as the active configuration in your gcloud properties.zWFailed to delete configuration [{0}].  Ensure you have the correct permissions on [{1}]N)r   r   rr   r   rw   r   r   r   r%   _EffectiveActiveConfigName_ActiveConfigNameFromFileremover}   r~   r   rs   r   s       r   DeleteConfigConfigurationStore.DeleteConfig   s     ;u=LLNE{2I77>>)$$
A6+    022!6+.0 0 /1166<f[6IK KJii	W J&!!'(-(D(D"FGHJ JJs   :C D!&DDc                    [        U SS9  [        R                  " 5       n[        X5      nU(       a>  [        R
                  R                  U5      (       d  [        SR                  U 5      5      e [        R                  " UR                  U 5        [        R                  SS9  g! [        R                   a*  n[        SR                  XR                  5      U5      eSnAff = f)a  Activates an existing named configuration.

Args:
  config_name: str, The name of the configuration to activate.

Raises:
  NamedConfigError: If the configuration does not exists.
  NamedConfigFileAccessError: If there a problem manipulating the
    configuration files.
Tr   z7Cannot activate configuration [{0}], it does not exist.zYFailed to activate configuration [{0}].  Ensure you have the correct permissions on [{1}]Nmark_changed)r   r   rr   r   rw   r   r   r   r%   r   r   named_config_activator_pathr   r   rJ   rK   r   s       r   ActivateConfig!ConfigurationStore.ActivateConfig"  s     ;t<LLNE{2I	22
C6+   ""

+
+[: ###6  &))/<<*>
	 s   1!B& &C$:%CC$c                 *   [        USS9  [        R                  " 5       n[        X5      nU(       a>  [        R
                  R                  U5      (       d  [        SR                  U 5      5      eU [        5       :X  a  [        SR                  U 5      5      eU [        5       :X  a  [        SR                  U 5      5      e[        X5      nU(       a>  [        R
                  R                  U5      (       a  [        SR                  X5      5      e [        R                  " U5      n[        R                  " XE5        [        R                  " U5        g! [        R                   a*  n[!        SR                  XR"                  5      U5      eSnAff = f)	ap  Renames an existing named configuration.

Args:
  config_name: str, The name of the configuration to rename.
  new_name: str, The new name of the configuration.

Raises:
  NamedConfigError: If the configuration does not exist, or if the
    configuration with new_name exists.
  NamedConfigFileAccessError: If there a problem manipulating the
    configuration files.
Tr   z5Cannot rename configuration [{0}], it does not exist.zLCannot rename configuration [{0}], it is the currently active configuration.zmCannot rename configuration [{0}], it is currently set as the active configuration in your gcloud properties.z8Cannot rename configuration [{0}], [{1}] already exists.zWFailed to rename configuration [{0}].  Ensure you have the correct permissions on [{1}]N)r   r   rr   r   rw   r   r   r   r%   r   r   r   ReadFileContentsr   r   r   r   r   )r<   new_namer   r   new_file_pathcontentsr   s          r   RenameConfigConfigurationStore.RenameConfigC  sP    8D9LLNE{2I	22
A6+    022!6+.0 0 /1166<f[6IK K #83M66
D6+(* *

,,Y7h""=;ii	 &))/<<*>
	 s   AE F(%FFr   NF)r   r   r   r   r   staticmethodrH   r   r   r   r   r   r   r   r   r   rk   rk      s    M+ + & &P  7  7D %J %JN 7 7@ 1 1r   rk   c                   0    \ rS rSrSrS rS rS rS rSr	g)	ru   ix  z.A class to encapsulate a single configuration.c                 d    Xl         X l        [        U[        R                  " 5       5      U l        g rB   )rt   r   r   r   rr   r   )r'   rt   r   s      r   r$   Configuration.__init__{  s     IN#D&,,.9DNr   c                     U R                   (       d  0 $ [        R                  " U R                   /5      R                  5       $ )a  Gets the properties defined in this configuration.

These are the properties literally defined in this file, not the effective
properties based on other configs or the environment.

Returns:
  {str, str}, A dictionary of all properties defined in this configuration
  file.
)r   r   PropertiesFileAllPropertiesrE   s    r   GetPropertiesConfiguration.GetProperties  s1     >>i))4>>*:;IIKKr   c                    U R                   (       d  [        U R                  5      e[        R                  R                  U R                   5      (       d$  [        SR                  U R                  5      5      e[        R                  " U R                   XU5        U R                  (       a  [        R                  SS9  gg)a  Persists a property to this configuration file.

Args:
  section: str, The section name of the property to set.
  name: str, The name of the property to set.
  value: str, The value to set for the given property, or None to unset it.

Raises:
  ReadOnlyConfigurationError: If you are trying to persist properties to
    the None configuration.
  NamedConfigError: If the configuration does not exist.
z>Cannot set property in configuration [{0}], it does not exist.Tr   N)r   r9   rt   rw   r   r   r   r%   r   PersistPropertyr   rJ   rK   )r'   sectionrt   r[   s       r   r   Configuration.PersistProperty  s     >>&tyy1177>>$..))
J6$))  ##DNNG5I~~%%4%8 r   c                 @    [         R                  U R                  5      $ )z8Mark this configuration as active in the activator file.)rk   r   rt   rE   s    r   ActivateConfiguration.Activate  s    ,,TYY77r   )r   r   rt   N)
r   r   r   r   r   r$   r   r   r   r   r   r   r   ru   ru   x  s    6:
L928r   ru   c                   b    \ rS rSrSrSr\R                  " 5       r\	S 5       r
\	SS j5       rSrg)rJ   i  zEAn interface for loading and caching the active properties from file.Nc                     [         R                  R                  5          [         R                  (       dO  [        R
                  " [        R                  " 5       R                  [        SS9R                  /5      [         l        [         R                  R                  5         [         R                  $ ! [         R                  R                  5         f = f)zLoads the set of active properties from file.

This includes both the installation configuration as well as the currently
active configuration file.

Returns:
  properties_file.PropertiesFile, The CloudSDK properties.
Frn   )rJ   _LOCKacquire_PROPERTIESr   r   r   rr   installation_properties_pathrH   r   releaser   r   r   LoadActivePropertiesFile.Load  s     &&(+!--+:+I+I\\^88,";$$-I/,0(   ((*+++   ((*s   A$B2 2 Cc                     S[         l        U (       a5  [        R                  " [        R
                  " 5       R                  S5        gg)a  Invalidate the cached property values.

Args:
  mark_changed: bool, True if we are invalidating because we persisted
    a change to the installation config, the active configuration, or
    changed the active configuration. If so, the config sentinel is touched.
Nr   )rJ   r   r   r   r   rr   config_sentinel_filer   s    r   rK   ActivePropertiesFile.Invalidate  s1     (,$""6<<>#F#FK r   r   r   )r   r   r   r   r   r   	threadingRLockr   r   r   rK   r   r   r   r   rJ   rJ     s>    M+
//
%, ,& 
L 
Lr   rJ   c                 R    [        5       nU(       d  [        U 5      n[        US5      $ )a;  Gets the currently active configuration.

There must always be an active configuration.  If there isn't this means
no configurations have been created yet and this will auto-create a default
configuration.  If there are legacy user properties, they will be migrated
to the newly created configuration.

Args:
  force_create: bool, If False and if there are no legacy properties, the
    new default configuration won't actually be created.  We just pretend
    that it exists, which is sufficient since it is empty.  We do this to
    avoid always creating the configuration when properties are just trying
    to be read.  This should only be set to False when seeing a
    PropertiesFile object.  All other operations must actually create the
    configuration.

Returns:
  Configuration, the currently active configuration.
T)r   _CreateDefaultConfigru   )ro   r<   s     r   rH   rH     s(    ( +,+ 
&|4K	{D	))r   c                  r    [         R                  5       n U (       d
  [        5       n U (       d
  [        5       n U $ )a	  Gets the currently active configuration.

It checks (in order):
  - Flag values
  - Environment variable values
  - The value set in the activator file

Returns:
  str, The name of the active configuration or None if no location declares
  an active configuration.
)FLAG_OVERRIDE_STACKrH   _ActiveConfigNameFromEnvr   )r<   s    r   r   r     s.     $002+	*,K	+-K	r   c                  j    [         R                  " [        R                  [        R
                  S5      $ )zGets the currently active configuration according to the environment.

Returns:
  str, The name of the active configuration or None.
N)r	   GetEncodedValuerw   environr   CLOUDSDK_ACTIVE_CONFIG_NAMEr   r   r   r   r     s(     
	!	!jj&44d
< <r   c                     [         R                  " 5       R                  n Sn [        R                  " U 5      nU(       a  [        USS9(       a  U$ SnU(       a  [        R                  " U 5        g! [        R                   a     N4[        R                   a>  n[        SR                  U [         R                  " 5       R                  5      U5      eSnAff = f)zGets the name of the user's active named config according to the file.

Returns:
  str, The name of the active configuration or None.
FTr   zActive configuration name could not be read from: [{0}]. Ensure you have sufficient read permissions on required active configuration in [{1}]N)r   rr   r   r   r   _IsValidConfigNameMissingFileErrorr   r   r%   rs   rw   r   )r   
is_invalidr<   r)   s       r   r   r     s     
	3	3$*C--d3K	K	= 
 IIdO	 
	$	$ 				 C
$	 
flln;;	<c	C CCs#   -A1 A1 1CC9CCc                 z    U [         :X  a  g[        R                  R                  UR                  [
        U -   5      $ )a  Gets the path to the properties file for a given configuration.

The file need not actually exist, it is just the path where it would be.

Args:
  config_name: str, The name of the configuration.
  paths: config.Paths, The instantiated Paths object to use to calculate the
    location.

Returns:
  str, The path to the file or None if this configuration does not have a
  corresponding file.
N)rv   rw   r   r4   rs   _CONFIG_FILE_PREFIX)r<   r   s     r   r   r   1  s5     **	e22)K7
9 9r   c                 n    U [         ;   a
  U(       d  g g[        R                  " [        U 5      (       d  gg)a   Determines if the given configuration name conforms to the standard.

Args:
  config_name: str, The name to check.
  allow_reserved: bool, Allows the given name to be one of the reserved
    configuration names.

Returns:
  True if valid, False otherwise.
FT)r5   ry   rz   _VALID_CONFIG_NAME_REGEXr<   r   s     r   r   r   E  s7     **  
 88,k::	r   c                 :    [        X5      (       d  [        U 5      eg)a	  Ensures that the given configuration name conforms to the standard.

Args:
  config_name: str, The name to check.
  allow_reserved: bool, Allows the given name to be one of the reserved
    configuration names.

Raises:
  InvalidConfigName: If the name is invalid.
N)r   r0   r   s     r   r   r   X  s     
K	8	8
K
(( 
9r   c                     [         R                  " 5       n [        R                  R	                  UR
                  5      (       d  [        U5      nU(       d  U (       ak  [        R                  " UR                  5        [        [        U5      n[        R                  " X25        [        R                  " UR
                  [        5        [        $ ! [        R                   a*  n[        SR                  UR                  5      U5      eSnAff = f)af  Create the default configuration and migrate legacy properties.

This will only do anything if there are no existing configurations.  If that
is true, it will create one called default.  If there are existing legacy
properties, it will populate the new configuration with those settings.
The old file will be marked as deprecated.

Args:
  force_create: bool, If False and no legacy properties exist to be migrated
    this will not physically create the default configuration.  This is ok
    as long as we are strictly reading properties from this configuration.

Returns:
  str, The default configuration name.
z^Failed to create the default configuration. Ensure your have the correct permissions on: [{0}]N)r   rr   rw   r   r   r    _GetAndDeprecateLegacyPropertiesr   r   rs   r   DEFAULT_CONFIG_NAMEr   r   r   r%   )ro   r   legacy_propertiestarget_filer   s        r   r   r   g  s      ,,.%Q77>>%;;<<
 ;5A	l5778$%8%@$$[D$$U%F%F%8	: 
	 
		 Q
$	((.u/K/K(LaQ QQs   B2C D#%DDzg# This properties file has been superseded by named configurations.
# Editing it will have no effect.

c                 2   Sn[         R                  R                  U R                  5      (       af  [        R
                  " U R                  5      nUR                  [        5      (       a  SnU$ [        R                  " U R                  [        U-   5        U$ )a  Gets the contents of the legacy  properties to include in a new config.

If the properties have already been imported, this returns nothing.  If not,
this will return the old properties and mark the old file as deprecated.

Args:
  paths: config.Paths, The instantiated Paths object to use to calculate the
    location.

Returns:
  str, The contents of the legacy properties file or ''.
r   )	rw   r   r   user_properties_pathr   r   r`   _LEGACY_DEPRECATION_MESSAGEr   )r   r   s     r   r   r     s     (WW^^E..//**5+E+EFH677 h
 
/ ""5#=#=#>#IK 
/r   )-r   
__future__r   r   r   r   rw   ry   r   googlecloudsdk.corer   r   "googlecloudsdk.core.configurationsr   googlecloudsdk.core.utilr	   r
   r   rv   r5   r   r   r   r{   r   r   r   r0   r9   objectr?   r   rk   ru   rJ   rH   r   r   r   r   r   r   r   r   r   r   r   r   <module>r      s   B &  '  	 	  & * > - 8   02  /  2 =J =?u ?1!1 1Q( QP PI IX )* X Xv18F 18h%L6 %LP*:(<D9(&)"J r   