
    )                         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
ZddZd Zd Zd Zd Zd Zd Zd Zd Zy)z0Common utilities and shared helpers for secrets.    )absolute_import)division)unicode_literalsN)
exceptions)yaml)
console_io)filesi   c                 :   | sy|xs t         }	 t        j                  | |      }t        |      |kD  r&t	        j
                  dj                  | |            |S # t        j                  $ r+}t	        j
                  dj                  | |            d}~ww xY w)a  Read data from the given file path or from stdin.

  This is similar to the cloudsdk built in ReadFromFileOrStdin, except that it
  limits the total size of the file and it returns None if given a None path.
  This makes the API in command surfaces a bit cleaner.

  Args:
      path (str): path to the file on disk or "-" for stdin
      max_bytes (int): maximum number of bytes
      is_binary (bool): if true, data will be read as binary

  Returns:
      result (str): result of reading the file
  N)binaryzGThe file [{path}] is larger than the maximum size of {max_bytes} bytes.)path	max_bytesz!Failed to read file [{path}]: {e}r   e)	DEFAULT_MAX_BYTESr   ReadFromFileOrStdinlenr   BadFileExceptionformatr	   Error)r   r   	is_binarydatar   s        .lib/googlecloudsdk/command_lib/secrets/util.pyReadFileOrStdinr      s     
,,)	D))$yAD
4y9''6ty69; ; K	 D

%
%+222BD DDs   AA B/&BBc                     | sy	 t        j                  | |d       y# t         j                  $ r+}t        j                  dj                  | |            d}~ww xY w)zWrites the given binary contents to the file at given path.

  Args:
      path (str): The file path to write to.
      content (str): The byte string to write.

  Raises:
      Error: If the file cannot be written.
  NT)privatez"Unable to write file [{path}]: {e}r   )r	   WriteBinaryFileContentsr   r   r   r   )r   contentr   s      r   WriteBinaryFiler   ?   s`     
E	!!$>	 E

%
%,333CE EEs    A&AAc                    d| vs| d   st        j                  d      g }g }| d   D ]  }d|vrt        j                  d      |j                  |d          d|v r4d|d   v r|j                  |d   d          nt        j                  d      |skt        |      t        |      k7  st        j                  d       d	||fS )
aL  "Reads user managed replication policy file and returns its data.

  Args:
      user_managed_policy (str): The json user managed message

  Returns:
      result (str): "user-managed"
      locations (list): Locations that are part of the user-managed replication
      keys (list): list of kms keys to be used for each replica.
  replicasz3Failed to find any replicas in user_managed policy.locationz*Failed to find a location in all replicas.customerManagedEncryption
kmsKeyNamezZFailed to find a kmsKeyName in customerManagedEncryption for replica at least one replica.zOnly some replicas have customerManagedEncryption. Please either add the missing field to the remaining replicas or remove it from all replicas.zuser-managed)r   r   appendr   )user_managed_policykeys	locationsreplicas       r   _ParseUserManagedPolicyr)   S   s     **2E3

%
%=? ?	$)$Z0g ''
68 8WZ()"g-	!<=	=G78FG)),- 	- D	S^+''  1" 
D	((    c                     | sdg g fS d| vrt        j                  d      | d   }d|vrt        j                  d      dg |d   gfS )a!  "Reads automatic replication policy file and returns its data.

  Args:
      automatic_policy (str): The json user managed message

  Returns:
      result (str): "automatic"
      locations (list): empty list
      keys (list): 0 or 1 KMS keys depending on whether the policy has CMEK
  	automaticr"   znFailed to parse replication policy. Expected automatic to contain either nothing or customerManagedEncryption.r#   z9Failed to find a kmsKeyName in customerManagedEncryption.)r   r   )automatic_policycmeks     r   _ParseAutomaticPolicyr/   x   sw     
B (88

%
%	78 8 
5	6$

%
%CE E	b4-.	..r*   c                 t    d| v rt        | d         S d| v rt        | d         S t        j                  d      )z9Reads replication policy dictionary and returns its data.userManagedr,   zWExpected to find either "userManaged" or "automatic" in replication, but found neither.)r)   r/   r   r   )replication_policys    r   _ParseReplicationDictr3      sN    (("#5m#DEE&& !3K!@AA##	 r*   c                     	 t        j                  |       }t        |      S # t        $ r Y nw xY w	 t	        j
                  |       }t        |      S # t        j                  $ r t        j                  d      w xY w)a  Reads replication policy file contents and returns its data.

  Reads the contents of a json or yaml replication policy file which conforms to
  https://cloud.google.com/secret-manager/docs/reference/rest/v1/projects.secrets#replication
  and returns data needed to create a Secret with that policy. If the file
  doesn't conform to the expected format, a BadFileException is raised.

  For Secrets with an automtic policy, locations is empty and keys has
  either 0 or 1 entry depending on whether the policy includes CMEK. For Secrets
  with a user managed policy, the number of keys returns is either 0 or is equal
  to the number of locations returned with the Nth key corresponding to the Nth
  location.

  Args:
      file_contents (str): The unvalidated contents fo the replication file.

  Returns:
      result (str): Either "user-managed" or "automatic".
      locations (list): Locations that are part of the user-managed replication
      keys (list): list of kms keys to be used for each replica.
  z8Failed to parse replication policy file as json or yaml.)	jsonloadsr3   
ValueErrorr   loadYAMLParseErrorr   r   )file_contentsr2   s     r   ParseReplicationFileContentsr;      s    ,	M2 !344	 		D=1 !344			 D

%
%BD DDs   " 	..A )A;c                    | j                  d      rg S t               }|D ]  }|j                  |j                          | j                  d      rW| j                  D ]  }|j                  |        g }|D ],  }|j                  |v s|j                  |j                         . |S | j                  d      rMg }|D ]  }|j                  |j                          | j                  D ]  }||vs|j                  |        |S y)aN  Applies updates to the list of topics on a secret.

  Preserves the original order of topics.

  Args:
    args (argparse.Namespace): The collection of user-provided arguments.
    original_topics (list): Topics configured on the secret prior to update.

  Returns:
      result (list): List of strings of topic names after update.
  clear_topicsremove_topics
add_topicsN)IsSpecifiedsetaddnamer>   discardr$   r?   )argsoriginal_topics
topics_settopic
topic_name
new_topicss         r   ApplyTopicsUpdaterK      s     
n%Iu*eNN5::  
o&((
$ )J 	z	!%**% ! 	l#J 

# !oo
	:	%*% &  $r*   c                    | j                  d      ri S t               }|j                  |D ci c]  }|j                  |j                   c}       | j                  d      rO| j
                  D ]  }||=  t               }|D ]*  }|j                  |v s|j                  ||j                  <   , |S | j                  d      r}t               }|j                  |D ci c]  }|j                  |j                   c}       |j                  | j                  j                         D ci c]  \  }}||
 c}}       |S yc c}w c c}w c c}}w )a{  Applies updates to the list of version-aliases on a secret.

  Makes no alterations to the original version aliases

  Args:
    args (argparse.Namespace): The collection of user-provided arguments.
    original_version_aliases (list): version-aliases configured on the secret
      prior to update.

  Returns:
      result (dict): dict of version_aliases pairs after update.
  clear_version_aliasesremove_version_aliasesupdate_version_aliasesN)r@   dictupdatekeyvaluerN   rO   items)rE   original_version_aliasesversion_aliases_dictpairaliasnew_version_aliasesversion_alias_pairversions           r   ApplyAliasUpdater\      s_    
-.I(@A(@txx(@AC	./,,
u
% -&6			#7	76H6N6N.223 7 01&*BC*B$4::	*BCE $ ; ; A A C  CUG 	w C    2 B 	D    EE)E
c                    | j                  d      ri S t               }|j                  |D ci c]  }|j                  |j                   c}       | j                  d      rO| j
                  D ]  }||=  t               }|D ]*  }|j                  |v s|j                  ||j                  <   , |S | j                  d      r}t               }|j                  |D ci c]  }|j                  |j                   c}       |j                  | j                  j                         D ci c]  \  }}||
 c}}       |S yc c}w c c}w c c}}w )ag  Applies updates to the list of annotations on a secret.

  Makes no alterations to the original annotations

  Args:
    args (argparse.Namespace): The collection of user-provided arguments.
    original_annotations (list): annotations configured on the secret prior to
      update.

  Returns:
      result (dict): dict of annotations pairs after update.
  clear_annotationsremove_annotationsupdate_annotationsN)r@   rP   rQ   rR   rS   r`   ra   rT   )rE   original_annotationsannotations_dictrW   
annotationnew_annotationsannotation_pairmetadatas           r   ApplyAnnotationsUpdaterh     sY    
)*IV(<=(<txx(<=?	*+--

:
& .fO/			 0	0/>/D/D++, 0 ,-fO*>?*>$4::	*>?A&*&=&=&C&C&E&E"Z 	H&E   . > 	@r]   )NT)__doc__
__future__r   r   r   r5   googlecloudsdk.callioper   googlecloudsdk.corer   googlecloudsdk.core.consoler   googlecloudsdk.core.utilr	   r   r   r   r)   r/   r3   r;   rK   r\   rh    r*   r   <module>rp      s]    7 &  '  . $ 2 * D@E(")J/0!DH#L$N$r*   