
    ]'                         d Z ddlmZ ddlmZ ddlm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Z G d dej$                        Zd Zd Zd Zd ZddZ	 	 	 ddZd Z	 ddZddZy)z0Convenience functions for dealing with metadata.    )absolute_import)division)unicode_literalsN)	constants)
exceptions)arg_parsers)log)filesc                       e Zd ZdZy)InvalidSshKeyExceptionz:InvalidSshKeyException is for invalid ssh keys in metadataN)__name__
__module____qualname____doc__     4lib/googlecloudsdk/api_lib/compute/metadata_utils.pyr   r   !   s    Br   r   c                     | j                         }|r\t        t        j                  |            D ];  \  }}|j                  j                  | j                   j                  ||             = |S )z/Converts a metadata dict to a Metadata message.)keyvalue)Metadatasortedsix	iteritemsitemsappendItemsValueListEntry)message_classesmetadata_dictmessager   r   s        r   _DictToMetadataMessager!   %   sg    $$&'S]]=9:
Umm?33GG H   ; 
.r   c                 b    i }| r*| j                   D ]  }|j                  ||j                  <    |S )z&Converts a Metadata message to a dict.)r   r   r   )metadata_messageresitems      r   _MetadataMessageToDictr&   0   s0    
# &&jjc$((m '	*r   c                    | j                  t        j                  d      }| j                  t        j                  d      }dj	                  ||f      }d|v rt        d      |j                  d      }g }|D ]"  }|st        |      s|j                  |       $ |r-d}|j                  dj	                  |            }t        |      y)a  Validates the ssh-key entries in metadata.

  The ssh-key entry in metadata should start with <username> and it cannot
  be a private key
  (i.e. <username>:ssh-rsa <key-blob> <username>@<example.com> or
  <username>:ssh-rsa <key-blob>
  google-ssh {"userName": <username>@<example.com>, "expireOn": <date>}
  when the key can expire.)

  Args:
    metadata_dict: A dictionary object containing metadata.

  Raises:
    InvalidSshKeyException: If the <username> at the front is missing or private
    key(s) are detected.
   
zPRIVATE KEYzHPrivate key(s) are detected. Note that only public keys should be added.zThe following key(s) are missing the <username> at the front
{}

Format ssh keys following https://cloud.google.com/compute/docs/instances/adding-removing-ssh-keysN)
getr   SSH_KEYS_METADATA_KEYSSH_KEYS_LEGACY_METADATA_KEYjoinr   split_SshKeyStartsWithKeyTyper   format)	r   ssh_keysssh_keys_legacyssh_keys_combinedkeyskeys_missing_usernamer   r    message_contents	            r   _ValidateSshKeysr7   9   s    $ y>>C(!%%i&L&L&(*/ii? ;<''
 	  
	 	 	&$c
',""3'  4G
 nnTYY/D%EFO
 
11 r   c                 z    t         j                  D cg c]  }| j                  |       }}t        |      S c c}w )zChecks if the key starts with any key type in constants.SSH_KEY_TYPES.

  Args:
    key: A ssh key in metadata.

  Returns:
    True if the key starts with any key type in constants.SSH_KEY_TYPES, returns
    false otherwise.

  )r   SSH_KEY_TYPES
startswithany)r   key_typekey_starts_with_typess      r   r/   r/   e   sC     09/F/F/F8cnnX/F   
"	##s   8c                    | xs i } |xs i }t        j                  |       }t        j                  |      D ]E  \  }}||v r$t	        j
                  dj                  |            t        j                  |      ||<   G |S )a  Returns the dict of metadata key:value pairs based on the given dicts.

  Args:
    metadata: A dict mapping metadata keys to metadata values or None.
    metadata_from_file: A dict mapping metadata keys to file names containing
      the keys' values or None.

  Raises:
    ToolException: If metadata and metadata_from_file contain duplicate
      keys or if there is a problem reading the contents of a file in
      metadata_from_file.

  Returns:
    A dict of metadata key:value pairs.
  z)Encountered duplicate metadata key [{0}].)	copydeepcopyr   r   compute_exceptionsDuplicateErrorr0   r
   ReadFileContents)metadatametadata_from_filenew_metadata_dictr   	file_paths        r   ConstructMetadataDictrH   v   s      ^()/RmmH-&89nc9
--
5
<
<S
AC C"33I>c	 :
 
r   c                    t        ||      }t        |      }|j                  |       	 t        |       t        | |      }|r|j                  |_        |S # t        $ r}t        j                  |       Y d}~Dd}~ww xY w)a  Creates a Metadata message from the given dicts of metadata.

  Args:
    message_classes: An object containing API message classes.
    metadata: A dict mapping metadata keys to metadata values or None.
    metadata_from_file: A dict mapping metadata keys to file names containing
      the keys' values or None.
    existing_metadata: If not None, the given metadata values are combined with
      this Metadata message.

  Raises:
    ToolException: If metadata and metadata_from_file contain duplicate
      keys or if there is a problem reading the contents of a file in
      metadata_from_file.

  Returns:
    A Metadata protobuf.
  N)	rH   r&   updater7   r   r	   warningr!   fingerprint)r   rD   rE   existing_metadatarF   existing_metadata_dictenew_metadata_messages           r   ConstructMetadataMessagerQ      s    , ,H6HI12CD 12+, 00FH '8'D'D$	 
  KKNNs   A 	A>A99A>c                 0    t        |       t        |      k(  S )zEReturns True if both metadata messages have the same key/value pairs.)r&   )	metadata1	metadata2s     r   MetadataEqualrU      s    			*.DY.O	OOr   c                     |r| j                         }n2|r0t        |      }|D ]  }|j                  |d        t        | |      }|j                  _        |S )a  Removes keys from existing_metadata.

  Args:
    message_classes: An object containing API message classes.
    existing_metadata: The Metadata message to remove keys from.
    keys: The keys to remove. This can be None if remove_all is True.
    remove_all: If True, all entries from existing_metadata are
      removed.

  Returns:
    A new Metadata message with entries removed and the same
      fingerprint as existing_metadata if existing_metadata contains
      a fingerprint.
  N)r   r&   popr!   rL   )r   rM   r4   
remove_allrP   rN   r   s          r   RemoveEntriesrY      sg      *33534EF  d+ 1/1 &7%B%B"	r   c                     d}|r|dz  }| j                  dt        j                  d      i |dt        j                         d}|r|dz  }| j                  d	t        j                  d      i |d
       y)z/Adds --metadata and --metadata-from-file flags.aK        Metadata to be made available to the guest operating system
      running on the instances. Each metadata entry is a key/value
      pair separated by an equals sign. Each metadata key must be unique
      and have a max of 128 bytes in length. Each value must have a max of
      256 KB in length. Multiple arguments can be
      passed to this flag, e.g.,
      ``--metadata key-1=value-1,key-2=value-2,key-3=value-3''.
      The combined total size for all metadata entries is 512 KB.

      In images that have Compute Engine tools installed on them,
      such as the
      link:https://cloud.google.com/compute/docs/images[official images],
      the following metadata keys have special meanings:

      *startup-script*::: Specifies a script that will be executed
      by the instances once they start running. For convenience,
      ``--metadata-from-file'' can be used to pull the value from a
      file.

      *startup-script-url*::: Same as ``startup-script'' except that
      the script contents are pulled from a publicly-accessible
      location on the web.


      For startup scripts on Windows instances, the following metadata keys
      have special meanings:
      ``windows-startup-script-url'',
      ``windows-startup-script-cmd'', ``windows-startup-script-bat'',
      ``windows-startup-script-ps1'', ``sysprep-specialize-script-url'',
      ``sysprep-specialize-script-cmd'', ``sysprep-specialize-script-bat'',
      and ``sysprep-specialize-script-ps1''. For more information, see
      [Running startup scripts](https://cloud.google.com/compute/docs/startupscript).
      zR

      At least one of [--metadata] or [--metadata-from-file] is required.
      z
--metadata   )
min_lengthz	KEY=VALUE)typedefaulthelpmetavaractionz      Same as ``--metadata'' except that the value for the entry will
      be read from a local file. This is useful for values that are
      too large such as ``startup-script'' contents.
      z--metadata-from-filezKEY=LOCAL_FILE_PATH)r]   r^   r_   r`   N)add_argumentr   ArgDictStoreOnceAction)parserrequiredmetadata_helpmetadata_from_file_helps       r   AddMetadataArgsri      s    !
-D  
 
M 	!,((  *

   
 
 	!,"#  %r   )NN)NNN)NF)F)r   
__future__r   r   r   r?   googlecloudsdk.api_lib.computer   r   googlecloudsdk.callioper   "googlecloudsdk.command_lib.computerA   googlecloudsdk.corer	   googlecloudsdk.core.utilr
   r   Errorr   r!   r&   r7   r/   rH   rQ   rU   rY   ri   r   r   r   <module>rq      s    7 &  '  4 5 / O # * 
CZ-- C)2X$": '+04/3%PP ).<>%r   