
    $                        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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.    )absolute_import)division)unicode_literalsN)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
_CreateTarr6   .   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        r5   _GetDockerignoreExclusionsrC   I   s     j/:,E'/WW^^L!!,,\:OmmO4O&99;<=Gs122G	.r7   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_filesrA   rE   r/   r-   s         r5   _GetIncludedPathsrK   b   sH    "  
	$$
,,
$
$T4=
9%L)	,r7   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)rC   rK   r   TemporaryDirectoryBinaryFileWriterr   r   r   gzipGzipFiler6   r*   r   StorageClientCopyFileToGCSr   )
r+   rJ   
object_refr,   dockerignore_contentsincluded_pathstemp_dirfr.   storage_clients
             r5   UploadSourcerZ   ~   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     r5   GetServiceTimeoutSecondsrc      s5    ! ../C>AC	#11	22r7   c                 R    U c  g[        U 5      n[        R                  " U5      S-   $ )zAReturns the service timeout duration string with suffix appended.Nr\   )rc   r    	text_type)ra   build_timeout_secss     r5   GetServiceTimeoutStringrg      s,    !/0DE	)	*S	00r7   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.)superri   __init__format)selffield	__class__s     r5   rm   InvalidBuildError.__init__   s"    	
T+	==CVE]Lr7    )__name__
__module____qualname____firstlineno____doc__rm   __static_attributes____classcell__)rq   s   @r5   ri   ri      s    NL Lr7   ri   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)getattrri   )buildfieldsrp   s      r5   _ValidateBuildFieldsr      s$    euT".e$$ r7   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}]r}   z-t.)r   args)stepsimages)r   GetMessagesModuler
   VALUESappcontainer_builder_imageGetr	   debugrn   Build	BuildStep)output_imagemessagesbuilders      r5   GetDefaultBuildr      s     ..0(!!99==?'))(//89	W&-t\3%G   I J^ 
 
 r7   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   rg   r
   r   r   cloud_build_timeoutr   r   r   r   SourceStorageSourcer   r   )r}   rT   r   s      r5   
FixUpBuildr      s    , ..0(

#
#E
*% 	,,11& 2 ( uAB)//3357%-&&%**"" +  ! %, 
,r7   )N)%rx   
__future__r   r   r   rP   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?   r6   rC   rK   rZ   rc   rg   
ValueErrorri   r   r   r   rs   r7   r5   <module>r      s   " L &  '  	  	  % = 6 # * * * 
 
 #/!@ 6285@31L
 L%0-r7   