o
    S`                    @   s  d dl Z d dlZd dlZd dlZd dlZd dlZd dl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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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 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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m0Z0 dd!lm1Z1 dd"lm2Z2 dd#lm3Z3 dd$lm4Z4 dd%lm5Z5 dd&l6m7Z7 dd'l8m9Z9 dd(l8m:Z: dd)l8m;Z; dd*l8m<Z< dd+l=m>Z> dd,lm?Z? dd-lm@Z@ dd.lAmBZB dd/lAmCZC dd0lAmDZD dd1lAmEZE dd2lAmFZF dd3lAmGZG d d4lHmIZI eJeKZLg d5ZMd6ZNd7ZOd8ZPG d9d: d:eQZRG d;d< d<eQZSG d=d> d>eQZTe	d?d@ZUe	dAdBZVe jWG dCdD dDe jXZYe jWG dEdF dFe jXZZe jWG dGdH dHe jXZ[G dIdJ dJZ\dKdL Z]G dMdN dNZ^G dOdP dPe^Z_G dQdR dRe^Z`G dSdT dTZaG dUdV dVeaZbG dWdX dXeaZcG dYdZ dZZdG d[d\ d\ZeG d]d^ d^Zfdd_d`Zgdadb Zhdcdd Zidedf Zjdgdh Zkdidj Zldkdl Zmdmdn Zndodp Zodqdr Zpdsdt Zqdudv Zrdwdx Zsdydz Ztd{d| Zud}d~ ZvG dd dZwG dd dZxG dd dZydS )    N)
namedtuple)OrderedDict)
attrgetter)APIError)ImageNotFound)NotFound)	LogConfig)Mount)version_gte)
version_lt)build_port_bindings)
split_port)convert_tmpfs_mounts   )__version__)const)progress_stream)DOCKER_CONFIG_KEYS)is_url)merge_environment)merge_labels)DependencyError)	MountSpec)ServicePort)
VolumeSpec)DEFAULT_TIMEOUT)IS_WINDOWS_PLATFORM)LABEL_CONFIG_HASH)LABEL_CONTAINER_NUMBER)LABEL_ONE_OFF)LABEL_PROJECT)LABEL_SERVICE)
LABEL_SLUG)LABEL_VERSION)NANOCPUS_SCALE)WINDOWS_LONGPATH_PREFIX)	Container)CompletedUnsuccessfully)HealthCheckFailed)NoHealthCheckConfigured)OperationFailedErrorparallel_execute)stream_output)StreamOutputError)generate_random_id)	json_hash)parse_bytes)parse_seconds_float)truncate_id)unique_everseen)binarystr_to_unicode)-cap_addcap_dropcgroup_parent	cpu_countcpu_percent
cpu_period	cpu_quotacpu_rt_periodcpu_rt_runtime
cpu_sharescpuscpusetdevice_cgroup_rulesdevicesdevice_requestsdns
dns_searchdns_optenv_fileextra_hosts	group_addinitipc	isolation	read_only
log_driverlog_opt	mem_limitmem_reservationmemswap_limitmem_swappinessoom_kill_disableoom_score_adjpid
pids_limit
privilegedrestartruntimesecurity_optshm_sizestorage_optsysctlsuserns_modevolumes_fromvolume_driverservice_startedservice_healthyservice_completed_successfullyc                   @      e Zd Zdd ZdS )
BuildErrorc                 C   s   || _ || _d S N)servicereason)selfri   rj    rl   1/usr/lib/python3/dist-packages/compose/service.py__init__w   s   
zBuildError.__init__N__name__
__module____qualname__rn   rl   rl   rl   rm   rg   v       rg   c                   @   rf   )NeedsBuildErrorc                 C   
   || _ d S rh   ri   rk   ri   rl   rl   rm   rn   }      
zNeedsBuildError.__init__Nro   rl   rl   rl   rm   rt   |   rs   rt   c                   @   s   e Zd ZdS )NoSuchImageErrorN)rp   rq   rr   rl   rl   rl   rm   ry      s    ry   ServiceNamezproject service numberConvergencePlanzaction containersc                   @   s(   e Zd ZdZdZdZdZedd ZdS )ConvergenceStrategyzrEnumeration for all possible convergence strategies. Values refer to
    when containers should be recreated.
    r         c                 C   s   | t | juS rh   )typeneverrk   rl   rl   rm   allows_recreate   s   z#ConvergenceStrategy.allows_recreateN)	rp   rq   rr   __doc__changedalwaysr   propertyr   rl   rl   rl   rm   r|      s    r|   c                   @      e Zd ZdZdZdZdZdS )	ImageTypez5Enumeration for the types of images known to compose.r   r   r}   N)rp   rq   rr   r   nonelocalallrl   rl   rl   rm   r      
    r   c                   @   r   )BuildActionz+Enumeration for the possible build actions.r   r   r}   N)rp   rq   rr   r   r   forceskiprl   rl   rl   rm   r      r   r   c                   @   s|  e Zd Z													dddZdd Zdd	d
ZdddZdd Zdd ZdddZ					dddZ
ejddfddZdd Zdd Zedd Zedd Zejdfdd Zd!d" Zdd#d$Zd%d& Zd'd( Zdd)d*Z				dd,d-Z	+	dd.d/Zd0d1 Zdd2d3Zdd4d5Zed6d7 Z dd8d9Z!dd:d;Z"d<d= Z#ed>d? Z$d@dA Z%dBdC Z&dDdE Z'dFdG Z(dHdI Z)dJdK Z*ddLdMZ+dNdO Z,ddPdQZ-dRdS Z.dTdU Z/dVdW Z0		ddXdYZ1dZd[ Z2dd\d]Z3d^d_ Z4		dd`daZ5dbdc Z6ddde Z7ddfdgZ8edhdi Z9ddjdkZ:dldm Z;dndo Z<dpdq Z=ddrdsZ>ddtduZ?dvdw Z@dxdy ZAdzd{ ZBd|d} ZCd~d ZDdS )ServiceNdefaultFr   c                 K   s   || _ || _|| _|| _|pg | _|pg | _|ptd | _|p"td | _	|p)t
d | _|p.i | _|	p3g | _|
| _|| _|| _|pAg | _d S rh   )nameclientprojectuse_networkinglinksra   IpcModeipc_modeNetworkModenetwork_modePidModepid_modenetworkssecrets	scale_numdefault_platformoptionsextra_labels)rk   r   r   r   r   r   ra   r   r   r   scaler   r   r   r   r   rl   rl   rm   rn      s   



zService.__init__c                 C   s   d | jS )Nz<Service: {}>)formatr   r   rl   rl   rm   __repr__   s   zService.__repr__c              
      s   |d u ri }| d j|d|pg  i ttd  fdd jj||dD }|r-|S | d j|dd|p9g  i tt fdd	td  fd
d jj||dD S )Nlabelone_offc                       g | ]	}t  j|qS rl   r&   from_psr   .0	containerr   rl   rm   
<listcomp>       z&Service.containers.<locals>.<listcomp>r   filtersTr   legacyc                    s   |   jS rh   )has_legacy_proj_namer   cr   rl   rm   <lambda>       z$Service.containers.<locals>.<lambda>c                    r   rl   r   r   r   rl   rm   r      r   )updatelabelslistfilterr   
containers)rk   stoppedr   r   r   resultrl   r   rm   r      s,   
 zService.containersc                 C   s4   | j dt|gdD ]}|  S td| j|)zReturn a :class:`compose.container.Container` for this service. The
        container must be active, and match `number`.
        {}={})r   zNo container found for {}_{})r   r   r   
ValueErrorr   )rk   numberr   rl   rl   rm   get_container   s   zService.get_containerc                 K   s,   | j dd}|D ]}| j|fi | q|S )NTr   )r   start_container_if_stopped)rk   r   r   r   rl   rl   rm   start   s   zService.startc                 C   sP   | j r|dkrtd| j| j f  |  r$|dkr&td| j  d S d S d S )Nr   zThe "%s" service is using the custom container name "%s". Docker requires each container to have a unique name. Remove the custom name to scale the service.zThe "%s" service specifies a port on the host. If multiple containers for this service are created on a single host, the port will clash.)custom_container_namelogwarningr   specifies_host_port)rk   desired_numrl   rl   rm   show_scale_warnings   s   

zService.show_scale_warningsc                    s2    |  jdd}t|}|D ]}| jsqtd|j   j||dd q||kr6td dS ||krz jdd}|t|kridd	 |D } fd
d	|D }|D ]}|	  qXt
t|t| }t|tdd}	 |	||dd ||k r|| }
t|tdd} ||
 d | dS dS )ar  
        Adjusts the number of containers to the specified number and ensures
        they are running.

        - creates containers until there are at least `desired_num`
        - stops containers until there are at most `desired_num` running
        - starts containers until there are at least `desired_num` running
        - removes all stopped containers
        Fr   z(Recreating container with legacy name %s)start_new_containerz)Desired container number already achievedNTc                 S      g | ]}|j s|qS rl   
is_runningr   r   rl   rl   rm   r   !  s
    z!Service.scale.<locals>.<listcomp>c                    s   g | ]
}  |gr|qS rl   )_containers_have_divergedr   r   rl   rm   r   &  s
    r   key)r   r   lenr   r   r   infor   recreate_containerremover   setsortedr   _execute_convergence_start
_downscale)rk   r   timeoutrunning_containersnum_runningr   all_containersstopped_containersdivergent_containerssorted_containersnum_to_stopsorted_running_containersrl   r   rm   r     sF   




zService.scalec              
   K   s   |    | j||p| j|d||d}d|v r"|s"td|d   ztj| jfi |W S  tyE } zt	d| j
t|jf d}~ww )zn
        Create a container for this service. If the image doesn't exist, attempt to pull
        it.
        r   )r   previous_containerr   zCreating %sz*Cannot create container for service %s: %sN)ensure_image_exists_get_container_create_options_next_container_numberr   r   r&   creater   r   r*   r   r5   explanation)rk   r   r   r   quietoverride_optionscontainer_optionsexrl   rl   rm   create_container<  s"   zService.create_containerc                 C   s   |   r|tjkr| j|d d S z|   W d S  ty!   Y nw |   s.| j|d d S |tjkr7t| | j|d t	
d| j d S )N)cli)silentzImage for service {} was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.)can_be_builtr   r   buildimagery   pullr   rt   r   r   r   r   )rk   do_buildr   r   rl   rl   rm   r   Z  s&   
zService.ensure_image_existsc                 C   0   z| j | jW S  ty   td| jw NzImage '{}' not found)r   inspect_distribution
image_namer   ry   r   r   rl   rl   rm   get_image_registry_datar  
   zService.get_image_registry_datac                 C   r   r   )r   inspect_imager   r   ry   r   r   rl   rl   rm   r   x  r   zService.imagec                 C   s    | j ddj| | jddS )Nr   z{project}_{s.name}z_-)sr   )r   getr   r   lstripr   rl   rl   rm   r   ~  s   zService.image_namec                 C   s(   | j d}|st| jjdr| j}|S )Nplatform1.35)r   r  r
   r   api_versionr   )rk   r  rl   rl   rm   r    s   zService.platformc                 C   s   | j dd}|rtdg S |stdg S |tju rtd|S |tju s(| |r-td|S dd |D }|r;td|S td	|S )
NTr   r   r   r   recreatec                 S   r   rl   r   r   rl   rl   rm   r         z,Service.convergence_plan.<locals>.<listcomp>noop)r   r{   r|   r   r   r   )rk   strategyr   r   r   rl   rl   rm   convergence_plan  s    






zService.convergence_planc              
   C   s   d }z| j }W n ty$ } ztd| jt| W Y d }~dS d }~ww d}|D ])}|| jr<td|j  d}q)|j	t
d }||krRtd|j|| d}q)|S )NzService %s has diverged: %sTFz$%s has diverged: Legacy project namez%s has diverged: %s != %s)config_hashry   r   debugr   strr   r   r   r  r   )rk   r   r  ehas_divergedr   container_config_hashrl   rl   rm   r     s4   

z!Service._containers_have_divergedc                    sv     }fdd fdd}tfddt||| D  fdd|d	\}}	|	 D ]}
t|
|S )
Nc                    sL   r| j dddd}n| j |dd} s|  r$s$| |S )NT)r   r   )r   r   rl   )r   attach_log_streamstart_container)ri   nr   )detachedr   r   rk   r   rl   rm   create_and_start  s   
z=Service._execute_convergence_create.<locals>.create_and_startc                    s(    rd | j| jdgS | j| jS )N_run)joinr   ri   get_container_namer   service_name)r   rk   rl   rm   get_name  s   z5Service._execute_convergence_create.<locals>.get_namec                    s   g | ]
}t  j j|qS rl   )rz   r   r   )r   indexr   rl   rm   r     s    z7Service._execute_convergence_create.<locals>.<listcomp>c                    s    | j S rh   r   r  )r  rk   rl   rm   r     r   z5Service._execute_convergence_create.<locals>.<lambda>Creating)r   r,   rangevaluesr*   )rk   r   r  r   r   r   ir  r   errorserrorrl   )r  r  r   r   rk   r   rm   _execute_convergence_create  s   	
	z#Service._execute_convergence_createc           
         s   |d urt ||kr||d   |d | } fdd}t||dd d\}}| D ]}	t|	|d urQt ||k rQ||t |   |S )Nc                    s   j |   dS )N)r   attach_logsr   renew_anonymous_volumes)r   r   r  r'  rk   r   r   rl   rm   r    s   z7Service._execute_convergence_recreate.<locals>.recreatec                 S      | j S rh   r   r   rl   rl   rm   r         z7Service._execute_convergence_recreate.<locals>.<lambda>
Recreatingr   r   r,   r!  r*   extendr%  )
rk   r   r   r   r  r   r'  r  r#  r$  rl   r)  rm   _execute_convergence_recreate  s"   z%Service._execute_convergence_recreatec           
         s   |d urt ||kr||d  | |d | }|r=dd |D }t| fdddd d\}}| D ]}	t|	|d urUt ||k rU||t |  | |S )Nc                 S   r   rl   r   r   rl   rl   rm   r     r  z6Service._execute_convergence_start.<locals>.<listcomp>c                    s   j |   ddS )NT)r&  r   )r   r   r  rk   rl   rm   r   
      z4Service._execute_convergence_start.<locals>.<lambda>c                 S   r*  rh   r+  r   rl   rl   rm   r     r,  Startingr.  )
rk   r   r   r   r  r   r   r  r#  r$  rl   r1  rm   r     s$   z"Service._execute_convergence_startc                    s$    fdd}t ||dd d d S )Nc                    s   | j  d |   d S )Nr   )stopstop_timeoutr   r(  rk   r   rl   rm   stop_and_remove  s   z+Service._downscale.<locals>.stop_and_removec                 S   r*  rh   r+  r   rl   rl   rm   r      r,  z$Service._downscale.<locals>.<lambda>zStopping and removingr+   )rk   r   r   r8  rl   r7  rm   r     s   zService._downscaleTc
                 C   s  |\}
}|d ur
|n| j }t|tdd}| | |
dv r*| j||||
dk|	dS |s.d }|
dkrN|rD|  d }|D ]}|| q<| ||||||S |
dkr[| |||||S |
d	kr}|t	|krn| |||||S |D ]
}t
d
|j  qp|S td|
)Nr   r   )r   r   r   )r   r   r  Idr   r  z%s is up-to-datezInvalid action: {})r   r   r   r   r%  r   reset_imager0  r   r   r   r   r   	Exceptionr   )rk   planr   r  r   scale_overriderescalereset_container_imager'  r   actionr   r   img_idr   rl   rl   rm   execute_convergence_plan$  sH   




z Service.execute_convergence_planc                 C   sZ   |j | |d |  | j|s|nd|jdd}|r |  |r'| | |  |S )zRecreate a container.

        The original container is renamed to a temporary name so that data
        volumes can be copied to the new container, before the original
        container is removed.
        r4  NT)r   r   r   )r5  r6  rename_to_tmp_namer   r   r  r  r   )rk   r   r   r&  r   r'  new_containerrl   rl   rm   r   Y  s   	

zService.recreate_containerc                 C   s,   |d ur|S t | jd}|d ur|S tS )Nstop_grace_period)r2   r   r  r   r7  rl   rl   rm   r6  p  s   zService.stop_timeoutc                 C   s4   |j s|std|j  |r|  | |S d S )NzStarting %s)r   r   r   r   r  r  )rk   r   r&  r   rl   rl   rm   r   x  s   
z"Service.start_container_if_stoppedc              
   C   sb   |  || z|  W |S  ty0 } zt|j}d|v r#td td| j	|d }~ww )Nz/driver failed programming external connectivityz+Host is already in use by another containerzCannot start service {}: {})
connect_container_to_networksr   r   r5   r   r   warnr*   r   r   )rk   r   use_network_aliasesr   explrl   rl   rm   r    s   


zService.start_containerc                 C   s   t t| j dd ddS )Nc                 S   s   | d  dpdS )Nr   priorityr   r  )trl   rl   rm   r     r2  z.Service.prioritized_networks.<locals>.<lambda>T)r   reverse)r   r   r   itemsr   rl   rl   rm   prioritized_networks  s   zService.prioritized_networksc                 C   s   | d}| j D ]=\}}||v r t||rq
| j|j| |r(| ||ng }| jj|j||| dd | dd | 	d| dd d q
d S )NzNetworkSettings.Networksipv4_addressipv6_addressFlink_local_ips)aliasesrP  rQ  r   rR  )
r  rO  rN  short_id_alias_existsr   !disconnect_container_from_networkid_get_aliasesconnect_container_to_network
_get_links)rk   r   rH  connected_networksnetworknetdefsrS  rl   rl   rm   rF    s    




z%Service.connect_container_to_networksc                 C   s<   |   D ]}td|j  |j| |d |  qd S )NzRemoving %sr4  )duplicate_containersr   r   r   r5  r6  r   )rk   r   r   rl   rl   rm   remove_duplicate_containers  s
   
z#Service.remove_duplicate_containersc                 c   sL    t | jdddd d}t }|D ]}|j|v r|V  q||j qd S )NTr   c                 S   s
   |  dS )NCreatedrK  r   rl   rl   rm   r     s   
 z.Service.duplicate_containers.<locals>.<lambda>r   )r   r   r   r   add)rk   r   numbersr   rl   rl   rm   r]    s   

zService.duplicate_containersc                 C   s   t |  S rh   )r0   config_dictr   rl   rl   rm   r       zService.config_hashc              	      sB    fdd} j |    jj jj j jdd  jD dS )Nc                      s$   z   d W S  ty   Y d S w Nr9  )r   ry   rl   r   rl   rm   image_id  s
   z%Service.config_dict.<locals>.image_idc                 S   s&   g | ]}t |jtr|jj|jfqS rl   )
isinstancesourcer   r   moder   vrl   rl   rm   r     s
    z'Service.config_dict.<locals>.<listcomp>)r   re  r   netr   r   r   ra   )	r   get_link_namesr   rV  r   rh  r   r   ra   )rk   re  rl   r   rm   rb    s   zService.config_dictc                 C   sh   | j j}| jj}| jj}|  |   |r|gng  |r|gng  |r&|gng  t| jdi 	  S )N
depends_on)
r   r  r   r   get_linked_service_namesget_volumes_from_namesr   r   r  keys)rk   net_namepid_namespaceipc_namespacerl   rl   rm   get_dependency_names  s   zService.get_dependency_namesc                 C   s  | j j}| jj}| jj}dd |  D }|dd |  D  ||r)|d ini  ||r4|d ini  ||r?|d ini  || jdi  | jdi 	 D ]3\}}|d t
krfdd ||< qU|d tkrsd	d ||< qU|d tkrd
d ||< qUtd|d |S )Nc                 S   s   i | ]}|d qS rh   rl   r   r   rl   rl   rm   
<dictcomp>      z2Service.get_dependency_configs.<locals>.<dictcomp>c                 s   s    | ]}|d fV  qd S rh   rl   ru  rl   rl   rm   	<genexpr>      
z1Service.get_dependency_configs.<locals>.<genexpr>rm  	conditionc                 S   s   dS )NTrl   r   rl   rl   rm   r     s    z0Service.get_dependency_configs.<locals>.<lambda>c                 S      |   S rh   )
is_healthyr{  rl   rl   rm   r         c                 S   r|  rh   )is_completed_successfullyr{  rl   rl   rm   r     r~  z%depends_on condition "{}" is invalid.)r   r  r   r   rn  r   ro  r   r  rN  CONDITION_STARTEDCONDITION_HEALTHY CONDITION_COMPLETED_SUCCESSFULLYr   r   )rk   rq  rr  rs  configssvcconfigrl   rl   rm   get_dependency_configs  s4   
zService.get_dependency_configsc                 C      dd | j D S )Nc                 S   s   g | ]\}}|j qS rl   r+  )r   ri   r  rl   rl   rm   r     r  z4Service.get_linked_service_names.<locals>.<listcomp>r   r   rl   rl   rm   rn       z Service.get_linked_service_namesc                 C   r  )Nc                 S   s   g | ]	\}}|j |fqS rl   r+  )r   ri   aliasrl   rl   rm   r         z*Service.get_link_names.<locals>.<listcomp>r  r   rl   rl   rm   rl    r  zService.get_link_namesc                 C   r  )Nc                 S   s    g | ]}t |jtr|jjqS rl   )rf  rg  r   r   )r   r   rl   rl   rm   r   
  s     z2Service.get_volumes_from_names.<locals>.<listcomp>ra   r   rl   rl   rm   ro  	  r  zService.get_volumes_from_namesc              
   C   sd   |rd S t | jdd| jddid| jdd| jdddid}dd |D }|s,d	S t|d	 S )
NTr   Fr   r   r   c                 S   s   g | ]
}|j d ur|j qS rh   r  r   rl   rl   rm   r         z2Service._next_container_number.<locals>.<listcomp>r   )	itertoolschain_fetch_containersr   max)rk   r   r   ra  rl   rl   rm   r     s   	zService._next_container_numberc                    s2    fddt d fdd jjdi |D S )Nc                    s*   z
t  j| d W S  ty   Y d S w rd  )r&   from_idr   r   r(  r   rl   rm   soft_inspect  s
   z/Service._fetch_containers.<locals>.soft_inspectc                       g | ]} |qS rl   rl   r   )r  rl   rm   r   $  s    z-Service._fetch_containers.<locals>.<listcomp>rl   )r   r   r   )rk   fetch_optionsrl   )rk   r  rm   r    s   zService._fetch_containersc                 C   s.   t | jh|r
|jhnt B t|ddB S )NrS  rl   )r   r   short_idr   r  )rk   r[  r   rl   rl   rm   rW  )  s   zService._get_aliasesc                 C   sp   | j si S | j | jj }| |i d}|dr"|d|d d< |dr0|d|d d< d| jj|iiS )N)Aliases
IPAMConfigrP  r  IPv4AddressrQ  IPv6AddressEndpointsConfig)r   r   rV  rW  r  )rk   r[  endpointrl   rl   rm   build_default_networking_config0  s   

z'Service.build_default_networking_configc                 C   s   i }| j D ]\}}| D ]}|j||p|j< |j||j< |j||j< qq|r@|  D ]}|j|| j< |j||j< |j||j< q+| jdpGg D ]}d|vrQ|}n|d\}}|||< qHdd | D S )Nexternal_links:c                 S   s   g | ]\}}||fqS rl   rl   )r   container_namer  rl   rl   rm   r   W  s    z&Service._get_links.<locals>.<listcomp>)r   r   r   name_without_projectr   r  splitrN  )rk   link_to_selfr   ri   	link_namer   external_linkrl   rl   rm   rY  A  s(   
zService._get_linksc                 C   r  )Nc                 S      g | ]}t |qS rl   )build_volume_from)r   specrl   rl   rm   r   ]      z-Service._get_volumes_from.<locals>.<listcomp>r  r   rl   rl   rm   _get_volumes_from\  r  zService._get_volumes_fromc                    s  | o| }|rt  nd } fddtD }|dg }|| |ds0  j|||d< |dd t j	j
dr^d|v r^d	|vr^d
|d v r^|d d
}	|	d |d< |	d |d	< t j	j
drqd jv rq d |d< d|v szd jv rtt|dg  j|d< d|v s|rtt|dg | |d< t  t jd|d|d< t jd|d|d<  |||\}} j|d< t|di  j|d j ||r߈ jnd ||d< tD ]}
||
d  q j||d|d<   }|r||d< t|d |d< |S )Nc                    s"   i | ]}| j v r| j | qS rl   r   )r   kr   rl   rm   rv  h  s
    

z9Service._get_container_create_options.<locals>.<dictcomp>volumesr   detachTz1.23hostname
domainname.r   r}   z1.25rE  r6  portsexposeenvironmentr   r   r   host_confignetworking_config) r/   r   popr   r  r  r   
setdefaultr   r   r  	partitionr
   r   r6  build_container_portsformatted_portsr   r   r   _parse_proxy_configr   _build_container_volume_optionsr   build_container_labelsr   r   r  HOST_CONFIG_KEYS_get_container_host_configr  format_environment)rk   r   r   r   r   add_config_hashslugr   override_volumespartsr   r  rl   r   rm   r   _  s   








	
z%Service._get_container_create_optionsc           
      C   s|  g }g }d|v rdd | dD }dd | dD }t|| j dp%g ||\}}|d | dd |p8i D |d< t| jjd	rPd
d |D pLd |d< n)| j dpWg |d< |D ]}|jrj|d |j	 q\||
  i |d |j	< q\|  }	|	rt| jjd	r|dd |	D  |d dd |	D  n| dpg |d< |d dd |	D  tt||d< ||fS )Nr  c                 S      g | ]	}t |tr|qS rl   )rf  r   ri  rl   rl   rm   r     s
    
z;Service._build_container_volume_options.<locals>.<listcomp>c                 S   r  rl   )rf  r   ri  rl   rl   rm   r     r  tmpfsr  c                 S   s   i | ]}|j i qS rl   )internalri  rl   rl   rm   rv    r  z;Service._build_container_volume_options.<locals>.<dictcomp>z1.30c                 S   r  rl   build_mountri  rl   rl   rm   r     r  mountsc                 s   s    | ]}|  V  qd S rh   )legacy_reprri  rl   rl   rm   rx        z:Service._build_container_volume_options.<locals>.<genexpr>c                 s   s    | ]}|j i fV  qd S rh   targetri  rl   rl   rm   rx    s    

c                 S   r  rl   r  ri  rl   rl   rm   r     r  binds)r  merge_volume_bindingsr   r   r
   r   r  is_tmpfsappendr  r  get_secret_volumesr   r/  r   r4   )
rk   r   r   r   container_volumescontainer_mountsr  affinitymsecret_volumesrl   rl   rm   r    s@   
z'Service._build_container_volume_optionsc           
   
   C   sJ  t | jfi |}|dd }t|dd }t|}d }t|dtr.|d}d|d< |dr=dd |dD nd }d }	d|v rNt|dt }	| j	j
dGi d	| j|d
dtt|dg d|dd|  d|ddd| jjd|dd|dd|dd|dd|dd|dd|dd|dd|dd|dd|dd|ddt|dd |d!|d!d"|d"d#| jjd|d$| jjd%|d%d&|d&d'|d'd(|d(d)|d)d*|d*d+|d+d,|d,d-|d-d.|d.d/|d/d|dd d0|d1|d1d2|d2d3|d3d4|	d5|d5d6|d7d8|d8d9|d9d:|d;d<|d=d>|d>d?|d?d@|d@dA|dAdB|dBdC|dCdD|dDdE|dEdF|dFS )HNloggingblkio_configrK   Tr\   c                 S      g | ]}|j qS rl   )value)r   orl   rl   rm   r     rw  z6Service._get_container_host_config.<locals>.<listcomp>r@   r   )r  port_bindingsr  r  ra   rY   Fr   rC   rD   rE   rG   rF   restart_policyrZ   r[   r6   r7   rQ   rR   rS   ulimits
log_configrI   rN   r   r   r8   r<   r]   r_   rX   r  rU   rV   rT   rJ   r`   	init_pathrM   r9   r:   	nano_cpusrb   cpuset_cpusrA   r?   r^   blkio_weightweightblkio_weight_deviceweight_devicedevice_read_bpsdevice_read_iopsdevice_write_bpsdevice_write_iopsr  rB   r;   r=   r>   rl   )dictr   r  convert_blkio_configget_log_configrf  r  intr$   r   create_host_configrY  r   r  r  r   rh  build_ulimitsr   r   )
rk   r   r   r   logging_dictr  r  r  r\   r  rl   rl   rm   r    s  


	


















 
!
"
#
$
%
&'(
)
*
+,
-
.
/
0
1
2
3
4
5
6
7
8
9
:
;z"Service._get_container_host_configc                    s   dd   fdd| j D S )Nc                 S   sV   | d j }|d u rdtj| d j}ntj|s!dtj|}td| d |ddS )Nsecretz{}/{}bindfileT)rN   )	r  r   r   SECRETS_PATHrg  ospathisabsr   )r  r  rl   rl   rm   
build_spec5  s   
z.Service.get_secret_volumes.<locals>.build_specc                    r  rl   rl   )r   r  r  rl   rm   r   >  r  z.Service.get_secret_volumes.<locals>.<listcomp>)r   r   rl   r  rm   r  4  s   	zService.get_secret_volumesc                 C   s  t tjd}|stj}td| j  | j	di }|	di 
 }|r)|| |   D ]
\}}||| q/t|	d}| jrOt| jjdrOtd|	sVt| jnt|
}|jdi d| d	|d
| jd|d|d|d|d|	dd d| |d|	dd d|d|	dd d|	dd d|	drt|	dnd d|	dd dd|rt|nd id|d|	d| j	dd d| jd|S ) NwzBuilding %sr   argscontextr  zEImpossible to perform platform-targeted builds for API version < 1.35ri   r  tagrmforcermr   nocache
dockerfile
cache_fromr   	buildargsr   r[  r  shmsizer]   rI   container_limitsmemorygziprM   r  output_streamrl   )openr  devnullsysstdoutr   r   r   r   r  copyr   r  rN  r  rewrite_build_pathr  r   r   r  r*   _ClientBuilder_CLIBuilderr   r   get_cache_fromr1   )rk   no_cacher   force_rmr
  build_args_overrider  r  r   r   progressr  
build_opts
build_argsr  rj  r  builderrl   rl   rm   r   @  sv   


	
zService.buildc                 C   s&   | dd }|d urdd |D }|S )Nr  c                 S   s   g | ]}|r|qS rl   rl   )r   r  rl   rl   rm   r   r  r  z*Service.get_cache_from.<locals>.<listcomp>rK  )rk   r  r  rl   rl   rm   r  o  s   zService.get_cache_fromc                 C   s
   d| j v S )Nr   r  r   rl   rl   rm   r   u  rx   zService.can_be_builtc                 C   sJ   |s| j ntdd| j }dt|dt| jdt|r!dgS dgS )Nz[_-] r   TrueFalse)r   resubr   r    r!   r   r   )rk   r   r   	proj_namerl   rl   rm   r   x  s   
zService.labelsc                 C   s   | j dS )Nr  r   r  r   rl   rl   rm   r     rc  zService.custom_container_namec                 C   sZ   | j r
|d u r
| j S t| j|||}dd | jdg D }||v r+td| j||S )Nc                 S   s   g | ]	}| d d qS )r  r   r  )r   linkrl   rl   rm   r     r  z.Service.get_container_name.<locals>.<listcomp>r  z3Service {} has a self-referential external link: {})r   build_container_namer   r   r  r   r   r   )rk   r  r   r  r  ext_links_originsrl   rl   rm   r    s   
zService.get_container_namec              
   C   s   |r|t jkr	dS |t jkr| jdrdS td| j z
| j	| j W dS  t
y8   td| j Y dS  tyR } ztd| j| W Y d }~dS d }~ww )NFr   zRemoving image %sTzImage %s not found.z)Failed to remove image for service %s: %s)r   r   r   r   r  r   r   r   r   remove_imager   r   r   r$  r   )rk   
image_typer  rl   rl   rm   r(    s    zService.remove_imagec                    s(   dd  t  fdd| jdg D S )Nc                 S   s\   t | tr| d}nt| \}}|d u rdS |d }t |ts"dS |\}}|d ur,dS dS )N	publishedFr   T)rf  r  r  r   tuple)bindingexternal_bindingsr  external_binding	host_portrl   rl   rm   has_host_port  s   

z2Service.specifies_host_port.<locals>.has_host_portc                 3   s    | ]} |V  qd S rh   rl   )r   r,  r0  rl   rm   rx    r  z.Service.specifies_host_port.<locals>.<genexpr>r  )anyr   r  r   rl   r1  rm   r     s    zService.specifies_host_portc              
   c   s    z;| j j|fi |}|r1ttjd}t||E d H  W d    W d S 1 s)w   Y  W d S t|tjE d H  W d S  tt	fy[ } z|sI t
t| W Y d }~d S d }~ww )Nr  )r   r   r  r  r  r-   r  r  r.   r   r   r$  r  )rk   repopull_kwargsr   ignore_pull_failuresoutputr  r  rl   rl   rm   _do_pull  s   &zService._do_pullc           	      C   s   d| j vrd S t| j d \}}}|pdd| jd}|s(td| j||| |d r7t| jj	dr7t
d| ||||}|rC|S t|S )	Nr   latestT)r  streamr  zPulling {} ({}{}{})...r  r  zDImpossible to perform platform-targeted pulls for API version < 1.35)r   parse_repository_tagr  r   r   r   r   r   r   r  r*   r7  r   get_digest_from_pull)	rk   r5  r   r9  r3  r  	separatorkwargsevent_streamrl   rl   rm   r     s"   

zService.pullc              
   C   s   d| j vs
d| j vrd S t| j d \}}}|pd}td| j||| | jj||dd}z
t	t
|tjW S  tyV } z|sD tt| W Y d }~d S d }~ww )Nr   r   r8  zPushing {} ({}{}{})...T)r  r9  )r   r:  r   r   r   r   r   pushr   get_digest_from_pushr-   r  r  r.   r$  r  )rk   ignore_push_failuresr3  r  r<  r6  r  rl   rl   rm   r?    s    
zService.pushc                 C   sZ   d}|   D ]$}|  |d}|du rt| j|dkr!d}q|dkr*t|jq|S )z Check that all containers for this service report healthy.
            Returns false if at least one healthcheck is pending.
            If an unhealthy container is detected, raise a HealthCheckFailed
            exception.
        TzState.Health.StatusNstartingF	unhealthy)r   inspectr  r)   r   r(   r  )rk   r   ctnrstatusrl   rl   rm   r}    s   


zService.is_healthyc                 C   sN   d}| j ddD ]}|  |ddkrd}q|jdkr$t|j|jq|S )a   Check that all containers for this service has completed successfully
            Returns false if at least one container does not exited and
            raises CompletedUnsuccessfully exception if at least one container
            exited with non-zero exit code.
        Tr   zState.StatusexitedFr   )r   rD  r  	exit_coder'   r  )rk   r   rE  rl   rl   rm   r  	  s   
z!Service.is_completed_successfullyc                 C   s   | j }d|jvr
i S t|d|j}|jd ||jd dp!i }ddddd}i }| D ]\}}||vr8q/| ||| < |||  < q/|S )	Nproxies_original_base_urlr   	FTP_PROXY
HTTP_PROXYHTTPS_PROXYNO_PROXY)ftpProxy	httpProxy
httpsProxynoProxy)r   _general_configsgetattrbase_urlr  rN  lower)rk   r   docker_hostproxy_config	permittedr   r  rj  rl   rl   rm   r    s(   

zService._parse_proxy_configc                 C   s   d| j vrg S | j dS )Nprofilesr#  r   rl   rl   rm   get_profiles1  s   
zService.get_profilesc                 C   s6   d| j vrdS | j d}|D ]	}||v r dS qdS )NrZ  TFr#  )rk   enabled_profilesservice_profilesprofilerl   rl   rm   enabled_for_profiles7  s   
zService.enabled_for_profiles)Nr   FNNNNNr   NNNN)FFNN)r   rh   )FNNF)FN)NFTNTFFN)NFTF)FF)T)F)
FFFNNFTFFN)FFF)Erp   rq   rr   rn   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r|   r   r
  r   r%  r0  r   r   rB  r   r6  r   r  rO  rF  r^  r]  r  rb  rt  r  rn  rl  ro  r   r  rW  r  rY  r  r   r  r  r  r   r  r   r   r   r  r(  r   r7  r   r?  r}  r  r  r[  r_  rl   rl   rl   rm   r      s    
"

	
;



&

5






!


X
,Q
/




r   c                 C   s    |  dj|dp
d}| j|v S )Nz&NetworkSettings.Networks.{net}.Aliases)rk  rl   )r  r   r  )r   r[  rS  rl   rl   rm   rT  D  s   

rT  c                   @   ,   e Zd Zdd Zedd Zedd ZdS )r   c                 C   ru   rh   _moderk   rh  rl   rl   rm   rn   K  rx   zIpcMode.__init__c                 C   r*  rh   ra  r   rl   rl   rm   rh  N     zIpcMode.modec                 C      d S rh   rl   r   rl   rl   rm   r  R     zIpcMode.service_nameNrp   rq   rr   rn   r   rh  r  rl   rl   rl   rm   r   J      
r   c                   @   r`  )ServiceIpcModec                 C   ru   rh   rv   rw   rl   rl   rm   rn   X  rx   zServiceIpcMode.__init__c                 C      | j jS rh   ri   r   r   rl   rl   rm   r  [     zServiceIpcMode.service_namec                 C   0   | j  }|rd|d j S td| j  d S )N
container:r   z[Service %s is trying to use reuse the IPC namespace of another service that is not running.ri   r   rV  r   r   r  rk   r   rl   rl   rm   rh  _     
zServiceIpcMode.modeNrp   rq   rr   rn   r   r  rh  rl   rl   rl   rm   ri  W  rh  ri  c                   @   rf   )ContainerIpcModec                 C      || _ d|j| _d S Nzcontainer:{}r   r   rV  rb  rk   r   rl   rl   rm   rn   m     zContainerIpcMode.__init__Nro   rl   rl   rl   rm   rs  l  rs   rs  c                   @   r`  )r   c                 C   ru   rh   ra  rc  rl   rl   rm   rn   s  rx   zPidMode.__init__c                 C   r*  rh   ra  r   rl   rl   rm   rh  v  rd  zPidMode.modec                 C   re  rh   rl   r   rl   rl   rm   r  z  rf  zPidMode.service_nameNrg  rl   rl   rl   rm   r   r  rh  r   c                   @   r`  )ServicePidModec                 C   ru   rh   rv   rw   rl   rl   rm   rn     rx   zServicePidMode.__init__c                 C   rj  rh   rk  r   rl   rl   rm   r    rl  zServicePidMode.service_namec                 C   rm  )Nrn  r   z[Service %s is trying to use reuse the PID namespace of another service that is not running.ro  rp  rl   rl   rm   rh    rq  zServicePidMode.modeNrr  rl   rl   rl   rm   ry    rh  ry  c                   @   rf   )ContainerPidModec                 C   rt  ru  rv  rw  rl   rl   rm   rn     rx  zContainerPidMode.__init__Nro   rl   rl   rl   rm   rz    rs   rz  c                   @   s,   e Zd ZdZdZdd Zedd ZeZdS )r   z,A `standard` network mode (ex: host, bridge)Nc                 C   ru   rh   r   )rk   r   rl   rl   rm   rn     rx   zNetworkMode.__init__c                 C   r*  rh   r{  r   rl   rl   rm   rV    rd  zNetworkMode.id	rp   rq   rr   r   r  rn   r   rV  rh  rl   rl   rl   rm   r     s    
r   c                   @   s4   e Zd ZdZdZdd Zedd Zedd ZdS )	ContainerNetworkModez5A network mode that uses a container's network stack.Nc                 C   ru   rh   r(  rw  rl   rl   rm   rn     rx   zContainerNetworkMode.__init__c                 C   rj  rh   r   rV  r   rl   rl   rm   rV    rl  zContainerNetworkMode.idc                 C   s   d| j j S )Nrn  r~  r   rl   rl   rm   rh    rc  zContainerNetworkMode.moder|  rl   rl   rl   rm   r}    s    
r}  c                   @   s4   e Zd ZdZdd Zedd ZeZedd ZdS )	ServiceNetworkModez3A network mode that uses a service's network stack.c                 C   ru   rh   rv   rw   rl   rl   rm   rn     rx   zServiceNetworkMode.__init__c                 C   rj  rh   rk  r   rl   rl   rm   rV    rl  zServiceNetworkMode.idc                 C   s0   | j  }|rd|d j S td| j  d S )Nrn  r   z[Service %s is trying to use reuse the network stack of another service that is not running.)ri   r   rV  r   r   rp  rl   rl   rm   rh    s   
zServiceNetworkMode.modeN)	rp   rq   rr   r   rn   r   rV  r  rh  rl   rl   rl   rm   r    s    
r  c                 C   s>   |  d|g}|r|dt|g n|t| d|S )Nz-_r  r  )r  r/  r3   r  r  r  )r   ri   r   r  bitsrl   rl   rm   r&    s
   
r&  c                 C   sh   d}d}|| v r|  |d\}}|||fS | d}}|| v r/|  |d\}}d|v r/| d}}|||fS )a  Splits image identification into base image path, tag/digest
    and it's separator.

    Example:

    >>> parse_repository_tag('user/repo@sha256:digest')
    ('user/repo', 'sha256:digest', '@')
    >>> parse_repository_tag('user/repo:v1')
    ('user/repo', 'v1', ':')
    r  @r   r  /)rsplit)	repo_pathtag_separatordigest_separatorr3  r  rl   rl   rm   r:    s   



r:  c                 C   st   i }t dd | D }|r2t|| ||\}}t| ||j |dd |D  |s+|r2dd|j i}t| |fS )z
        Return a list of volume bindings for a container. Container data volumes
        are replaced by those from the previous container.
        Anonymous mounts are updated in place.
    c                 s   s    | ]
}|j rt|V  qd S rh   )externalbuild_volume_bindingr   volumerl   rl   rm   rx    s    
z(merge_volume_bindings.<locals>.<genexpr>c                 s   s    | ]}t |V  qd S rh   )r  r  rl   rl   rm   rx    ry  zaffinity:container=)r   get_container_data_volumeswarn_on_masked_volumeri   r   rV  r   r!  )r  r  r   r  r  volume_bindingsold_volumes
old_mountsrl   rl   rm   r    s   
r  c                 C   s
  g }|pg }dd |  dpi D }dd | jd  dpi D }t|| D ]7}|jr-q'|jt| v r7q'| |j}|s@q'| dsFq'|jd	d |D v rQq'|j|d d
}|| q'd}	|D ]}|j	dkrkqc| |j
}
|
rx|
 dsyqc|
d |_d}	qc||	fS )z
        Find the container data volumes that are in `volumes_option`, and return
        a mapping of volume bindings for those volumes.
        Anonymous volume mounts are updated in place instead.
    c                 S   s   i | ]}|d  |qS )Destinationrl   )r   mountrl   rl   rm   rv  #      z.get_container_data_volumes.<locals>.<dictcomp>Mountsc                 S   s   g | ]}t |qS rl   )r   parser  rl   rl   rm   r   (  r  z.get_container_data_volumes.<locals>.<listcomp>ContainerConfigVolumesNamec                 S   r  rl   r  )r   r  rl   rl   rm   r   C  r2  )r  Fr  T)r  image_configr   r  r  r   rp  _replacer  r   r  rg  )r   volumes_optiontmpfs_optionmounts_optionr  r  image_volumesr  r  updated_mounts
ctnr_mountrl   rl   rm   r    s@   


r  c                 C   sX   dd |D }| D ] }|j r)|j|v r)||j|j kr)tdj||j|j d q	d S )Nc                 S   s   i | ]}|j |jqS rl   )r  r  r  rl   rl   rm   rv  Z  r  z)warn_on_masked_volume.<locals>.<dictcomp>zService "{service}" is using volume "{volume}" from the previous container. Host mapping "{host_path}" has no effect. Remove the existing containers (with `docker-compose rm {service}`) to use the host volume mapping.)ri   r  	host_path)r  r  r  r   r   r   )r  r  ri   r  rl   rl   rm   r  Y  s&   r  c                 C   s   | j |  fS rh   )r  repr)volume_specrl   rl   rm   r  o     r  c                 C   sn   t | jtr&| jjdd}|sd| j j| jS |d }d|j| jS t | jtr5d| jj| jS dS )z
    volume_from can be either a service or a container. We want to return the
    container.id and format it into a string complete with the mode.
    Tr   {}:{}r   N)	rf  rg  r   r   r   r   rV  rh  r&   )volume_from_specr   r   rl   rl   rm   r  s  s   
r  c                 C   s`   i }| j r| j| j  D ]\}}|| j v r| j | ||< qtd| j| j| j| j| jd|S )N)r   r  rg  rN   consistencyrl   )	r   options_mapr   rN  r	   r  rg  rN   r  )
mount_specr=  optionsdk_namerl   rl   rm   r    s   
r  c                 C   sj   t | pi }|dd |D  |d urt||t< |d ur"||t< t|t< |r3td|  ||t	< |S )Nc                 s   s    | ]	}| d dV  qdS )r  r   Nr$  )r   r   rl   rl   rm   rx    s    z)build_container_labels.<locals>.<genexpr>zAdded config hash: %s)
r  r   r  r   r"   r   r#   r   r  r   )label_optionsservice_labelsr   r  r  r   rl   rl   rm   r    s   r  c                 C   sf   | sd S g }|   D ]&\}}t|tr||||d q
t|tr0d|i}|| || q
|S )N)r   softhardr   )rN  rf  r  r  r  r   )ulimit_configr  
limit_namesoft_hard_valuesulimit_dictrl   rl   rm   r    s   



r  c                 C   s4   | r|  ddnd}| r|  dd nd }t||dS )Ndriverr  r   )r   r  )r  r   )r  rO   log_optionsrl   rl   rm   r    s   r  c                    s   dd   fdd|   D S )Nc                 S   s.   |d u r| S t |tr|d}dj| |dS )Nzutf-8z{key}={value}r   r  )rf  bytesdecoder   r  rl   rl   rm   
format_env  s
   

z&format_environment.<locals>.format_envc                    s   g | ]} | qS rl   rl   )r   itemr  rl   rm   r     r  z&format_environment.<locals>.<listcomp>)rN  )r  rl   r  rm   r    s   r  c                 C   s6   g }| D ]}t |tr||  q|| q|S rh   )rf  r   r  r  )r  r   portrl   rl   rm   r    s   
r  c                 C   s`   g }| | dg  }|D ]!}t|\}}|D ]}t|}d|v r't|d}|| qq|S )Nr  r  )r  r   r  r+  r  r  )container_portsr   r  	all_ports
port_rangeinternal_ranger  r  rl   rl   rm   r    s   r  c                 C   sh   i }| d u r|S |  d|d< dD ] }|| vrqg }| | D ]}|dd | D  q|||< q|S )Nr  )r  r  r  r  r  c                 S   s   i | ]	\}}|  |qS rl   )
capitalize)r   r  rj  rl   rl   rm   rv    r  z(convert_blkio_config.<locals>.<dictcomp>)r  r  rN  )r  r   fieldarrr  rl   rl   rm   r    s   
r  c                 C   s*   t rt| s| tsttj|  } | S rh   )r   r   
startswithr%   r  r  normpath)r  rl   rl   rm   r    s   r  c                   @   T   e Zd Zdd ZdddddddddddddddddddddddddejfddZdS )r  c                 C   ru   rh   )r   )rk   r   rl   rl   rm   rn     rx   z_ClientBuilder.__init__NFTc           #   
   C   s  | j jdi d|d|d|d|d|d|d|d|d	|d
|d|d|d|d|d|d|d|d|}z	tt||}W n tyY } zt|t|d }~ww | j   d } |D ]}!d|!v rzt	d|!
dd}"|"rz|"d} qc| d u rt||r|!d| S )Nr  r  r  r  r   r  r  r   r  r  r   r  r  rI   r	  r  rM   r  r9  zSuccessfully built ([0-9a-f]+)r  r   Unknownrl   )r   r   r   r-   r.   rg   r  closer   searchr  group)#rk   ri   r  r  r   fileobjr  r  r   custom_contextencodingr   r  r  r	  r  r  r  r  r   r  r  r   squashrI   r  rM   use_config_proxyr  build_output
all_eventsr  re  eventmatchrl   rl   rm   r     sl   	


z_ClientBuilder.buildrp   rq   rr   rn   r  r  r   rl   rl   rl   rm   r        r  c                   @   r  )r  c                 C   ru   rh   )	_progress)rk   r  rl   rl   rm   rn   7  rx   z_CLIBuilder.__init__NFTc           %      C   s  |rt j|rt j||}t }t }|d| |d| |	d| |
d| |d| |	d|d |	d| |
d	| |	d
| j |
d| |	d| |	d| |	d| |	d| |	d| |rt|trdd | D }|D ]}|	dd| q||g} tj| |tjdd}!|!  |!jdkrt|dW d   n1 sw   Y  t|}"|" }#|#dd  }$W d   n1 sw   Y  t | |$S )ah  
        Args:
            service (str): Service to be built
            path (str): Path to the directory containing the Dockerfile
            buildargs (dict): A dictionary of build arguments
            cache_from (:py:class:`list`): A list of images used for build
                cache resolution
            container_limits (dict): A dictionary of limits applied to each
                container created by the build process. Valid keys:
                - memory (int): set memory limit for build
                - memswap (int): Total memory (memory + swap), -1 to disable
                    swap
                - cpushares (int): CPU shares (relative weight)
                - cpusetcpus (str): CPUs in which to allow execution, e.g.,
                    ``"0-3"``, ``"0,1"``
            custom_context (bool): Optional if using ``fileobj``
            decode (bool): If set to ``True``, the returned stream will be
                decoded into dicts on the fly. Default ``False``
            dockerfile (str): path within the build context to the Dockerfile
            encoding (str): The encoding for a stream. Set to ``gzip`` for
                compressing
            extra_hosts (dict): Extra hosts to add to /etc/hosts in building
                containers, as a mapping of hostname to IP address.
            fileobj: A file object to use as the Dockerfile. (Or a file-like
                object)
            forcerm (bool): Always remove intermediate containers, even after
                unsuccessful builds
            isolation (str): Isolation technology used during build.
                Default: `None`.
            labels (dict): A dictionary of labels to set on the image
            network_mode (str): networking mode for the run commands during
                build
            nocache (bool): Don't use the cache when set to ``True``
            platform (str): Platform in the format ``os[/arch[/variant]]``
            pull (bool): Downloads any updates to the FROM image in Dockerfiles
            quiet (bool): Whether to return the status
            rm (bool): Remove intermediate containers. The ``docker build``
                command now defaults to ``--rm=true``, but we have kept the old
                default of `False` to preserve backward compatibility
            shmsize (int): Size of `/dev/shm` in bytes. The size must be
                greater than 0. If omitted the system uses 64MB
            squash (bool): Squash the resulting images layers into a
                single layer.
            tag (str): A tag to add to the final image
            target (str): Name of the build-stage to build in a multi-stage
                Dockerfile
            timeout (int): HTTP timeout
            use_config_proxy (bool): If ``True``, and if the docker client
                configuration file (``~/.docker/config.json`` by default)
                contains a proxy configuration, the corresponding environment
                variables will be set in the container being built.
            output_stream (writer): stream to use for build logs
        Returns:
            A generator for the build output.
        z--build-argz--cache-fromz--filez
--force-rmz--labelz--memoryr
  z	--networkz
--no-cachez
--progressz--pullz--tagz--targetz	--iidfilez
--platformz--isolationc                 S   s   g | ]
\}}d  ||qS )r  )r   )r   hostiprl   rl   rm   r     r  z%_CLIBuilder.build.<locals>.<listcomp>z
--add-hostz{}T)r  stderruniversal_newlinesr   zBuild failedNr  r   )r  r  isdirr  tempfilemktemp_CommandBuilder
add_paramsadd_listadd_argadd_flagr  r  rf  r  rN  r   r   
subprocessPopenr  r  communicate
returncoderg   r  readliner  stripr   )%rk   ri   r  r  r   r  r  r  r   r  r  r   r  r  r	  r  r  r  r  r   r  r  r   r  rI   r  rM   r  r  iidfilecommand_builderr  r  pflinere  rl   rl   rm   r   :  sP   ?




z_CLIBuilder.buildr  rl   rl   rl   rm   r  6  r  r  c                   @   s<   e Zd Zdd Zdd Zdd Zdd Zd	d
 Zdd ZdS )r  c                 C   s   ddg| _ d S )Ndockerr   _argsr   rl   rl   rm   rn     r  z_CommandBuilder.__init__c                 C   s    |r| j |t|g d S d S rh   )r  r/  r  )rk   r   r  rl   rl   rm   r    s   z_CommandBuilder.add_argc                 C   s   |r| j |g d S d S rh   r  r/  )rk   r   flagrl   rl   rm   r    s   z_CommandBuilder.add_flagc                 C   s6   |r|  D ]\}}| j|d||g qd S d S )Nr   )rN  r  r/  r   )rk   r   paramsr   valrl   rl   rm   r    s
   z_CommandBuilder.add_paramsc                 C   s&   |r|D ]}| j ||g qd S d S rh   r  )rk   r   r!  r  rl   rl   rm   r    s
   z_CommandBuilder.add_listc                 C   s
   | j | S rh   r  )rk   r  rl   rl   rm   r     rx   z_CommandBuilder.buildN)	rp   rq   rr   rn   r  r  r  r  r   rl   rl   rl   rm   r    s    r  rh   )zenumr  r  r  r   r  r  r  collectionsr   r   operatorr   docker.errorsr   r   r   docker.typesr   r	   docker.utilsr
   r   docker.utils.portsr   r   docker.utils.utilsr   r  r   r   r   r  r   r   r   r   config.errorsr   config.typesr   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r   r&   r#  r'   r(   r)   r*   parallelr,   r-   r.   utilsr/   r0   r1   r2   r3   r4   compose.cli.utilsr5   	getLoggerrp   r   r  r  r  r  r;  rg   rt   ry   rz   r{   uniqueEnumr|   r   r   r   rT  r   ri  rs  r   ry  rz  r   r}  r  r&  r:  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rl   rl   rl   rm   <module>   s    
0

         %
?

8n