
    8                     4   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
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Jr  SrSr\R<                  " \5      r\R<                  " \5      r \S-   r!\R<                  " SRE                  \!\S9\RF                  \RH                  -  S9r%\R<                  " S\RL                  S9r'\RP                   " S S\RR                  5      5       r*S r+S r,S r-S r.S r/\RP                  \R`                  " \Rb                  Rd                  \Rb                  Rf                  \Rb                  Rh                  5       " S  S!\Rj                  5      5       5       r6g)"z;Implements the command for modifying the user's SSH config.    )absolute_import)division)unicode_literalsN)base_classes)lister)path_simplifier)utils)base)
exceptions)	ssh_utils)ssh)log)
properties)files)	platformsz# Google Compute Engine Sectionz&# End of Google Compute Engine Sectiona  
#
# The following has been auto-generated by "gcloud compute config-ssh"
# to make accessing your Google Compute Engine virtual machines easier.
#
# To remove this blob, run:
#
#   gcloud compute config-ssh --remove
#
# You can also manually remove this blob by deleting everything from
# here until the comment that contains the string "End of Google Compute
# Engine Section".
#
# You should not hand-edit this section, unless you are deleting it.
#
z"(^{begin}\n*?(Host.*?)\n+{end}\n?))beginend)flagszHost (.*?)\nc                   0   ^  \ rS rSrSrSU 4S jjrSrU =r$ )MultipleComputeSectionsErrorJ   z)Multiple compute sections are disallowed.c                 ^   > [         [        U ]  SR                  U[        [
        5      5        g )NzFound more than one Google Compute Engine section in [{0}]. You can either delete [{0}] and let this command recreate it for you or you can manually delete all sections marked with [{1}] and [{2}].)superr   __init__format_BEGIN_MARKER_END_MARKER)selfssh_config_file	__class__s     !lib/surface/compute/config_ssh.pyr   %MultipleComputeSectionsError.__init__N   s)    	
&6	 "6/=+N	P     )zthe SSH configuration file)__name__
__module____qualname____firstlineno____doc__r   __static_attributes____classcell__)r    s   @r!   r   r   J   s    1P Pr#   r   c                     [         R                  U 5      nU(       d  U $ [        U 5      (       d
  [        5       eU SUR	                  S5       XR                  S5      S -   $ )aT  Returns the contents of ssh_config_file with compute section removed.

Args:
 existing_content: str, Current content of ssh config file.

Raises:
  MultipleComputeSectionsError: If the config file has multiple compute
    sections already.

Returns:
  A string containing the contents of ssh_config_file with the compute
  section removed.
N   )_SECTION_REsearch_ComputeSectionValidr   startr   existing_contentmatchs     r!   _RemoveComputeSectionr5   V   s[     

-
.%		.	/	/
&
((	/5;;q>	*-=iilm-L	LLr#   c                     [        [        R                  U 5      5      S:w  a  g[        [        R                  U 5      5      S:w  a  g[        R                  U 5      nU(       d  gg)z1False if compute section invalid, otherwise True.r-   FT)len	_BEGIN_REfindall_END_REr.   r/   r2   s     r!   r0   r0   o   sR    		+	,-2)	*+q0


-
.%		r#   c                    [         R                  U 5      nU(       d.  U(       a"  U S   S:w  a  U S-  n U SS S:w  a  U S-  n X-   nU$ U n U$ [        U 5      (       d
  [        5       eU(       d  U $ [        R                  U5      nUR                  S5      R                  S5      nU Vs/ s H/  n[        R                  U5      R                  S5      U;  d  M-  UPM1     nnUR                  [         R                  U5      R                  S5      5        SR                  U5      nU SUR                  S5       U-   XR                  S5      S -   nU$ s  snf )	a  Merges a new compute section into an existing compute section.

Appends new host entries into the compute section. If any of the newly
appended entries match the host of a previous compute section entry, the
previous entry is removed. The resulting merged configuration file contents
are returned. This function has no side effects, and does not directly change
the contents of the configuration file.

Args:
 existing_content: str, Current content of ssh config file.
 compute_section: str, New content to be added to the compute section.

Raises:
  MultipleComputeSectionsError: If the config file has multiple compute
    sections already.

Returns:
  A string containing the new contents of the ssh configuration file after
  merging the new entries for the compute section.

Nz

   r-   r   )r.   r/   r0   r   _HOST_REr9   groupsplitappendjoinr1   r   )r3   compute_sectionr4   new_content	new_hostsexisting_hostshosthostss           r!   _MergeComputeSectionsrK   }   s^   , 

-
.%	  
"		%D 	"#	&	(D $6k, 
' %k& 
%   011
&
((   1I[[^))&1N, nd0E0K0KA0N1TnE 	LL##O4::1=>kk%(O#Aekk!n5"##IIaLM23K 
s   ',EEc                     U R                   [        R                  " U R                  5      [        R
                  R                  R                  R                  SS9/nSR                  U5      $ )z)Returns the alias for the given instance.T)required.)
namer   Namezoner   VALUEScoreprojectGetrD   )instance_resourcepartss     r!   _CreateAliasrX      s\     ,112$$(($(7%
 
%r#   c                    / nU  H{  n[         R                  " USS9nSR                  UR                  5      nU(       d  M<  UR	                  [
        R                  " SR                  [        U5      UUUUS95      5        M}     U(       az  [        R                  " 5       nUR                  [        5        U H  nUR                  U5        M     UR                  [        5        UR                  S5        UR                  5       $ g)zGReturns a string representing the Compute section that should be added.T)no_raisezcompute.{0}a            Host {alias}
              HostName {external_ip_address}
              IdentityFile {private_key_file}
              UserKnownHostsFile={known_hosts_file}
              HostKeyAlias={host_key_alias}
              IdentitiesOnly=yes
              CheckHostIP=no

          )aliasexternal_ip_addressprivate_key_fileknown_hosts_filehost_key_aliasr=    )r   GetExternalIPAddressr   idextendtextwrapdedentrX   ioStringIOwrite_HEADERr   getvalue)		instancesr]   r^   temp_bufinstancer\   r_   bufis	            r!   _BuildComputeSectionrp      s    (h&&x$? "))(++6Noohoo 	' f<1)<&6&6$2	  45 6 * 
++-CIIg	iil IIkIIdO<<>r#   c                   L    \ rS rSrSr\R                  r\S 5       r	S r
S rSrg)	ConfigSSH   a  Populate SSH config files with Host entries from each instance.

*{command}* makes SSHing to virtual machine instances easier
by adding an alias for each instance to the user SSH configuration
(`~/.ssh/config`) file.

In most cases, it is sufficient to run:

  $ {command}

Each instance will be given an alias of the form
`NAME.ZONE.PROJECT`. For example, if `example-instance` resides in
`us-central1-a`, you can SSH to it by running:

  $ ssh example-instance.us-central1-a.MY-PROJECT

On some platforms, the host alias can be tab-completed, making
the long alias less daunting to type.

The aliases created interface with SSH-based programs like
*scp(1)*, so it is possible to use the aliases elsewhere:

  $ scp ~/MY-FILE example-instance.us-central1-a.MY-PROJECT:~

Whenever instances are added, removed, or their external IP addresses are
changed, the remove command must be run to clear the existing configuration
and then the command can set executed to set the configuration to the current
state.

This command ensures that the user's public SSH key is present
in the project's metadata. If the user does not have a public
SSH key, one is generated using *ssh-keygen(1)* (if the `--quiet`
flag is given, the generated key will have an empty passphrase).

## EXAMPLES
To populate SSH config file with Host entries from each running instance, run:

  $ {command}

To remove the change to the SSH config file by this command, run:

  $ {command} --remove
c                     [         R                  R                  U 5        U R                  SSR	                  [
        R                  5      S9  U R                  SSSS9  U R                  SSS	S9  g
)zPSet up arguments for this command.

Args:
  parser: An argparse.ArgumentParser.
z--ssh-config-filezo        Specifies an alternative per-user SSH configuration file. By
        default, this is ``{0}''.
        )helpz	--dry-run
store_truezwIf provided, the proposed changes to the SSH config file are printed to standard output and no actual changes are made.)actionru   z--removezOIf provided, any changes made to the SSH config file by this tool are reverted.N)r   BaseSSHHelperArgsadd_argumentr   r   PER_USER_SSH_CONFIG_FILE)parsers    r!   ry   ConfigSSH.Args  s       (
 F3//0  2 K  M #  %r#   c           
      :   / n[         R                  " UR                  R                  [        R
                  R                  R                  R                  5       SSUR                  R                  UR                  US9nU(       a  [        R                  " USS9  U$ )z<Returns a generator of all running instances in the project.Nzstatus eq RUNNING)servicerT   requested_zonesfilter_exprhttp	batch_urlerrorszCould not fetch all instances:)error_message)r   GetZonalResourcesapitools_clientrk   r   rR   rS   rT   	GetOrFailr   r   r	   RaiseToolException)r   clientr   rk   s       r!   GetRunningInstancesConfigSSH.GetRunningInstances8  s    F((&&00!!&&..88:'##((""I 
 @Br#   c           
         [         R                  " U R                  5       5      nUR                  n[        R
                  " 5       nUR                  U5        UR                  R                  UR                  SS9  [        R                  " UR                  =(       d    [        R                  5      nSn [        R                  " U5      nUR(                  (       a  Sn	 [+        U5      n
OUR/                  U[        R0                  " SS9S5        [3        U R5                  U5      5      nU(       a9  [7        XdR                  R8                  [        R:                  R<                  5      n	OSn	U(       a  UR(                  (       d   [?        Xy5      n
O	U(       d  U	n
UR@                  (       a)  ["        RB                  RE                  W
=(       d    S5        gW
U:w  Ga  [F        RH                  RK                  U5      (       a  [L        RN                  RQ                  5       [L        RN                  RR                  La  [F        RT                  " U5      RV                  nU[T        RX                  -  [T        RZ                  [T        R\                  -  :X  a.  U[T        R^                  -  S:X  a  U[T        R`                  -  S:X  d  ["        Rb                  " S5        [        Rd                  " XZSS	9  U	(       aM  ["        RB                  RE                  [f        Rh                  " S
R'                  [k        US   5      S95      5        gU	S:X  a  U(       a  ["        Rb                  " S5        gU(       d)  UR(                  (       d  ["        Rb                  " S5        ggg! [        R                    a2  nSn["        R$                  " SR'                  XX5      5         SnAGNSnAff = f! [,         a    [-        U5      ef = f! [,         a    [-        U5      ef = f)z!See ssh_utils.BaseSSHCommand.Run.T)allow_passphraseNr`   z.SSH Config File [{0}] could not be opened: {1})warn_on_account_userr   zVInvalid permissions on [{0}]. Please change to match ssh requirements (see man 5 ssh).)privatez          You should now be able to use ssh/scp with your instances.
          For example, try running:

            $ ssh {alias}

          )r[   zSNo host aliases were added to your SSH configs because instances have no public IP.zNo host aliases were added to your SSH configs because you do not have any running instances. Try running this command again after running some instances.)6r   ComputeApiHolderReleaseTrackr   r   rx   RunkeysEnsureKeysExistforce_key_file_overwriter   ExpandHomeDirr   r   r{   ReadFileContentsErrorr   debugr   remover5   r   EnsureSSHKeyIsInProjectGetDefaultSshUsernamelistr   rp   key_file
KnownHostsDEFAULT_PATHrK   dry_runoutrh   ospathexistsr   OperatingSystemCurrentWINDOWSstatst_modeS_IRWXUS_IWUSRS_IRUSRS_IWGRPS_IWOTHwarningWriteFileContentsrd   re   rX   )r   argsholderr   
ssh_helperr   rk   r3   erE   rF   ssh_config_permss               r!   r   ConfigSSH.RunI  s   **4+<+<+>?F]]F((*JNN4OO##D$A$A59 $ ; ))< < <>O I-//@ {{o<+,<= ((
#++FNt//78i	.//1L1LN <+,<N #k||	ggmmK%2&&&
''..
)
)

#
#
+
+
-

#
#
+
+,77?3;; t||+t||dll/JJt||+q0t||+q0
++./ oDI	ggmmHOO % f<	!5f68 9 
B	9	kk ! t{{	kk$%  +YI ;; -	ii@+- -- * <*?;;< * <*?;;<s0   5N O O2 O$'OOO/2Pr$   N)r%   r&   r'   r(   r)   r
   TOOLS_CATEGORYcategorystaticmethodry   r   r   r*   r$   r#   r!   rr   rr      s2    *X   (% %6"X%r#   rr   )7r)   
__future__r   r   r   rf   r   rer   rd   googlecloudsdk.api_lib.computer   r   r   r	   googlecloudsdk.callioper
   r   "googlecloudsdk.command_lib.computer   #googlecloudsdk.command_lib.util.sshr   googlecloudsdk.corer   r   googlecloudsdk.core.utilr   r   r   r   compiler8   r:   ri   r   	MULTILINEDOTALLr.   
IGNORECASEr@   UniverseCompatibleToolExceptionr   r5   r0   rK   rX   rp   ReleaseTracksr   GABETAALPHACommandrr   r$   r#   r!   <module>r      sy    B &  ' 	 	 	   7 1 : 0 ( . 8 3 # * * . 26JJ}%	
**[
!
  " jj>EE
{ F $!||bii79 ::oR]]; P:#;#; P PM2;|"J D%%(($*;*;*@*@%%++-t% t%- t%r#   