
    $                         S 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rSS
KJr  SS/rS rS rS rSS jrS rS r " S S\5      rS rS rS r g)zEUtility methods to upload source to GCS and call Cloud Build service.    N)encoding)cloudbuild_util)storage_api)log)
properties)files)times)filter
Dockerfile.dockerignorec                 6   [         R                  R                  U 5      n[        R                  " SUS9n[        U5       H2  n[         R                  R                  XF5      nUR                  XvSS9  M4     [        R                  " U5       Hz  u  p[        R                  " U	R                  5       5      n
[        R                  " US9n[        U
R                  5       5      Ul        UR#                  XS9  U
R%                  5         M|     UR%                  5         g)a  Create tarfile for upload to GCS.

The third-party code closes the tarfile after creating, which does not
allow us to write generated files after calling docker.utils.tar
since gzipped tarfiles can't be opened in append mode.

Args:
  upload_dir: the directory to be archived
  gen_files: Generated files to write to the tar
  paths: allowed paths in the tarfile
  gz: gzipped tarfile object
wmodefileobjF)arcname	recursive)name)r   N)ospathabspathtarfileopensortedjoinaddsix	iteritemsioBytesIOencodeTarInfolengetvaluesizeaddfileclose)
upload_dir	gen_filespathsgzroottr   	full_pathr   contents
genfileobjtar_infos               -lib/googlecloudsdk/api_lib/app/cloud_build.py
_CreateTarr3   +   s     
	$$llR(!UmdT(IEE)UE3  i0ndHOO-.JD)H
++-.HMIIhI+ 1 '')    c                 v   [         R                  R                  U S5      n[        5       nSn[         R                  R	                  U5      (       a  [
        R                  " U5      nOUR                  S5      nU(       a9  [        [        [        UR                  5       5      5      nU[        [        5      -  nU$ )a  Helper function to read the .dockerignore on disk or in generated files.

Args:
  upload_dir: the path to the root directory.
  gen_files: dict of filename to contents of generated files.

Returns:
  Set of exclusion expressions from the dockerignore file.
r   N)r   r   r   setexistsr   ReadFileContentsgetr
   bool
splitlinesBLOCKLISTED_DOCKERIGNORE_PATHS)r(   r)   dockerignoreexcludeignore_contentss        r2   _GetDockerignoreExclusionsr@   F   s     j/:,E'/WW^^L!!,,\:OmmO4O&99;<=Gs122G	.r4   c                     SSK n[        R                  R                  U 5      nUR                  R                  U[        U5      5      nUR                  U5        U$ )a  Helper function to filter paths in root using dockerignore and skip_files.

We iterate separately to filter on skip_files in order to preserve expected
behavior (standard deployment skips directories if they contain only files
ignored by skip_files).

Args:
  upload_dir: the path to the root directory.
  source_files: [str], relative paths to upload.
  exclude: the .dockerignore file exclusions.

Returns:
  Set of paths (relative to upload_dir) to include.
r   N)dockerr   r   r   utilsexclude_pathslistintersection_update)r(   source_filesr>   rB   r,   r*   s         r2   _GetIncludedPathsrH   _   sH    "  
	$$
,,
$
$T4=
9%L)	,r4   c                    U=(       d    0 n[        X5      n[        XU5      n[        R                  " 5        n[        R                  " [
        R                  R                  US5      5      n[        R                  " SUS9 n[        XXX5        SSS5        UR                  5         [        R                  " 5       n	U	R                  UR                  U5        SSS5        g! , (       d  f       NX= f! , (       d  f       g= f)a  Upload a gzipped tarball of the source directory to GCS.

Note: To provide parity with docker's behavior, we must respect .dockerignore.

Args:
  upload_dir: the directory to be archived.
  source_files: [str], relative paths to upload.
  object_ref: storage_util.ObjectReference, the Cloud Storage location to
    upload the source tarball to.
  gen_files: dict of filename to (str) contents of generated config and
    source context files.
zsrc.tgzwbr   N)r@   rH   r   TemporaryDirectoryBinaryFileWriterr   r   r   gzipGzipFiler3   r'   r   StorageClientCopyFileToGCSr   )
r(   rG   
object_refr)   dockerignore_contentsincluded_pathstemp_dirfr+   storage_clients
             r2   UploadSourcerW   {   s     o2)4ZK$ 57. !Xrww||Hi@AA	D!	,; 
-GGI ..0N  4 "!	,	, "!s%   A
C2C!A	C2!
C/	+C22
D c                 ^    U c  g[         R                  " U SS9n[        UR                  5      $ )zAReturns the service timeout in seconds given the duration string.Ns)default_suffix)r	   ParseDurationinttotal_seconds)timeout_property_strbuild_timeout_durations     r2   GetServiceTimeoutSecondsr`      s5    ! ../C>AC	#11	22r4   c                 R    U c  g[        U 5      n[        R                  " U5      S-   $ )zAReturns the service timeout duration string with suffix appended.NrY   )r`   r   	text_type)r^   build_timeout_secss     r2   GetServiceTimeoutStringrd      s,    !/0DE	)	*S	00r4   c                   ,   ^  \ rS rSrSrU 4S jrSrU =r$ )InvalidBuildError   zFError indicating that ExecuteCloudBuild was given a bad Build message.c                 J   > [         [        U ]  SR                  U5      5        g )NzeField [{}] was provided, but should not have been. You may be using an improper Cloud Build pipeline.)superrf   __init__format)selffield	__class__s     r2   rj   InvalidBuildError.__init__   s"    	
T+	==CVE]Lr4    )__name__
__module____qualname____firstlineno____doc__rj   __static_attributes____classcell__)rn   s   @r2   rf   rf      s    NL Lr4   rf   c                 F    U H  n[        XS5      c  M  [        U5      e   g)zDValidates that a Build message doesn't have fields that we populate.N)getattrrf   )buildfieldsrm   s      r2   _ValidateBuildFieldsr|      s$    euT".e$$ r4   c           	      "   [         R                  " 5       n[        R                  R                  R
                  R                  5       n[        R                  " SR                  U5      5        UR                  UR                  USSU S/S9/U /S9$ )a  Get the default build for this runtime.

This build just uses the latest docker builder image (location pulled from the
app/container_builder_image property) to run a `docker build` with the given
tag.

Args:
  output_image: GCR location for the output docker image (e.g.
    `gcr.io/test-gae/hardcoded-output-tag`)

Returns:
  Build, a CloudBuild Build message with the given steps (ready to be given to
    FixUpBuild).
zUsing builder image: [{0}]rz   z-t.)r   args)stepsimages)r   GetMessagesModuler   VALUESappcontainer_builder_imageGetr   debugrk   Build	BuildStep)output_imagemessagesbuilders      r2   GetDefaultBuildr      s     ..0(!!99==?'))(//89	W&-t\3%G   I J^ 
 
 r4   c                    [         R                  " 5       n[        R                  " U 5      n U R                  (       a7  U R                  R
                  R                  [        R                  " S5      S9  [        U S5        [        [        R                  R                  R                  R                  5       5      U l        UR"                  U l        UR'                  UR)                  UR"                  UR*                  S9S9U l        U $ )a  Return a modified Build object with run-time values populated.

Specifically:
- `source` is pulled from the given object_ref
- `timeout` comes from the app/cloud_build_timeout property
- `logsBucket` uses the bucket from object_ref

Args:
  build: cloudbuild Build message. The Build to modify. Fields 'timeout',
    'source', and 'logsBucket' will be added and may not be given.
  object_ref: storage_util.ObjectReference, the Cloud Storage location of the
    source tarball.

Returns:
  Build, (copy) of the given Build message with the specified fields
    populated.

Raises:
  InvalidBuildError: if the Build message had one of the fields this function
    sets pre-populated
key)r   )sourcetimeout
logsBucket)bucketobject)storageSource)r   r   r   CopyProtoMessagesubstitutionsadditionalPropertiessortoperator
attrgetterr|   rd   r   r   r   cloud_build_timeoutr   r   r   r   SourceStorageSourcer   r   )rz   rQ   r   s      r2   
FixUpBuildr      s    , ..0(

#
#E
*% 	,,11& 2 ( uAB)//3357%-&&%**"" +  ! %, 
,r4   )N)!ru   rM   r   r   r   r   apitools.base.pyr   !googlecloudsdk.api_lib.cloudbuildr   googlecloudsdk.api_lib.storager   googlecloudsdk.corer   r   googlecloudsdk.core.utilr   r	   r   	six.movesr
   r<   r3   r@   rH   rW   r`   rd   
ValueErrorrf   r|   r   r   rp   r4   r2   <module>r      s   " L  	  	  % = 6 # * * * 
 
 #/!@ 6285@31L
 L%0-r4   