U
    ]                  ,   @   s  d dl mZ d dl m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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"m0Z0 ddl"m1Z1 dd l"m2Z2 dd!l"m3Z3 dd"l"m4Z4 dd#l"m5Z5 dd$l"m6Z6 dd%l"m7Z7 dd&l"m8Z8 dd'l"m9Z9 dd(l:m;Z; dd)l<m=Z= dd*l<m>Z> dd+l<m?Z? dd,l@mAZA dd-l#mBZB dd.l#mCZC dd/lDmEZE dd0lDmFZF dd1lDmGZG dd2lDmHZH dd3lDmIZI dd4lDmJZJ ejKrd dlLZMnd dlMZMeNeOZPd5d6d7d8d9d:d;d<d=d>d?d@dAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`g,ZQdaZRdbZSG dcdd ddeTZUG dedf dfeTZVG dgdh dheTZWedidjZXedkdlZYejZG dmdn dnej[Z\ejZG dodp dpej[Z]ejZG dqdr drej[Z^G dsdt dte_Z`dudv ZaG dwdx dxe_ZbG dydz dzebZcG d{d| d|ebZdG d}d~ d~e_ZeG dd de_ZfG dd de_ZgdddZhdd Zidd Zjdd Zkdd Zldd Zmdd Zndd Zodd Zpdd Zqdd Zrdd Zsdd Ztdd Zudd Zvdd ZwG dd de_ZxG dd de_ZydS )    )absolute_import)unicode_literalsN)
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)HealthCheckFailed)NoHealthCheckConfigured)OperationFailedErrorparallel_execute)stream_output)StreamOutputError)generate_random_id)	json_hash)parse_bytes)parse_seconds_float)truncate_id)unique_everseen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dns
dns_searchdns_optZenv_fileextra_hosts	group_addinitipc	isolation	read_only
log_driverZ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_driverZservice_startedZservice_healthyc                   @   s   e Zd Zdd ZdS )
BuildErrorc                 C   s   || _ || _d S N)servicereason)selfrb   rc    re   1/usr/lib/python3/dist-packages/compose/service.py__init__{   s    zBuildError.__init__N__name__
__module____qualname__rg   re   re   re   rf   r`   z   s   r`   c                   @   s   e Zd Zdd ZdS )NeedsBuildErrorc                 C   s
   || _ d S ra   rb   rd   rb   re   re   rf   rg      s    zNeedsBuildError.__init__Nrh   re   re   re   rf   rl      s   rl   c                   @   s   e Zd ZdS )NoSuchImageErrorN)ri   rj   rk   re   re   re   rf   ro      s   ro   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k	S ra   )typeneverrd   re   re   rf   allows_recreate   s    z#ConvergenceStrategy.allows_recreateN)	ri   rj   rk   __doc__changedalwaysrv   propertyrx   re   re   re   rf   rr      s   rr   c                   @   s   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   rs   N)ri   rj   rk   ry   nonelocalallre   re   re   rf   r}      s   r}   c                   @   s   e Zd ZdZdZdZdZdS )BuildActionz+Enumeration for the possible build actions.r   r   rs   N)ri   rj   rk   ry   r~   forceskipre   re   re   rf   r      s   r   c                   @   sB  e Zd Zdddddddddddg fddZdd Zdzd	d
Zd{ddZdd Zdd Zd|ddZ	d}d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fdd Zd!d" Zd#d$ Zd%d& Zd'd( Zd~d)d*Zdd,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 Z0ddXdYZ1dZd[ Z2dd\d]Z3d^d_ Z4dd`daZ5dbdc Z6ddde Z7ddfdgZ8edhdi Z9ddjdkZ:dldm Z;dndo Z<dpdq Z=ddrdsZ>ddtduZ?dvdw Z@dxdy ZAdS )ServiceNdefaultFr   c                 K   sx   || _ || _|| _|| _|pg | _|p(g | _|p6td | _|pDtd | _	|pNi | _
|	pXg | _|
| _|| _|| _|| _d S ra   )nameclientprojectuse_networkinglinksr^   NetworkModenetwork_modePidModepid_modenetworkssecrets	scale_numdefault_platformoptionsextra_labels)rd   r   r   r   r   r   r^   r   r   r   scaler   r   r   r   re   re   rf   rg      s    



zService.__init__c                 C   s   d | jS )Nz<Service: {}>)formatr   rw   re   re   rf   __repr__   s    zService.__repr__c              
      s   |d kri }| d j|d|p"g  i ttd  fdd jj||dD }|rZ|S | d j|dd|prg  i tt fdd	td  fd
d jj||dD S )Nlabelone_offc                    s   g | ]}t  j|qS re   r(   Zfrom_psr   .0	containerrw   re   rf   
<listcomp>   s   z&Service.containers.<locals>.<listcomp>r   filtersTr   legacyc                    s   |   jS ra   )has_legacy_proj_namer   crw   re   rf   <lambda>       z$Service.containers.<locals>.<lambda>c                    s   g | ]}t  j|qS re   r   r   rw   re   rf   r      s   )updatelabelslistfilterr   
containers)rd   stoppedr   r   r   resultre   rw   rf   r      s.    
 
 zService.containersc                 C   s8   | j dt|gdD ]
}|  S td| j|f dS )zReturn a :class:`compose.container.Container` for this service. The
        container must be active, and match `number`.
        {0}={1})r   zNo container found for %s_%sN)r   r   r    
ValueErrorr   )rd   numberr   re   re   rf   get_container   s    zService.get_containerc                 K   s(   | j dd}|D ]}| j|f| q|S )NTr   )r   start_container_if_stopped)rd   r   r   r   re   re   rf   start   s    zService.startc                 C   sH   | j r$|dkr$td| j| j f  |  rD|dkrDtd| j  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)rd   desired_numre   re   rf   show_scale_warnings   s    
zService.show_scale_warningsc                    s0    |  jdd}t|}|D ]2}| js4q"td|j   j||dd q"||krltd dS ||kr jdd}|t|krdd	 |D } fd
d	|D }|D ]}|	  qt
t|t| }t|tdd}	 |	||dd ||k r,|| }
t|tdd} ||
 d | 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   s   g | ]}|j s|qS re   
is_runningr   r   re   re   rf   r   #  s     z!Service.scale.<locals>.<listcomp>c                    s   g | ]}  |gr|qS re   )_containers_have_divergedr   rw   re   rf   r   (  s     r   key)r   r   lenr   r   r   infor   recreate_containerremover   setsortedr   _execute_convergence_start
_downscale)rd   r   timeoutZrunning_containersZnum_runningr   Zall_containersZstopped_containersZdivergent_containersZsorted_containersZnum_to_stopZsorted_running_containersre   rw   rf   r     sL    



    
zService.scalec              
   K   s   |    | j||p| j|d||d}d|krD|sDtd|d   ztj| jf|W S  tk
r } zt	d| j
|jf W 5 d}~X Y nX dS )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   explanation)rd   r   r   r   quietoverride_optionscontainer_optionsexre   re   rf   create_container>  s    
zService.create_containerc                 C   s   |   r"|tjkr"| j|d d S z|   W d S  tk
rD   Y nX |   s^| j|d d S |tjkrpt| | 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imagero   pullr   rl   r   r   r   r   )rd   Zdo_buildr   r   re   re   rf   r   \  s&    
zService.ensure_image_existsc                 C   s:   z| j | jW S  tk
r4   td| jY nX d S NzImage '{}' not found)r   Zinspect_distribution
image_namer   ro   r   rw   re   re   rf   get_image_registry_datat  s    zService.get_image_registry_datac                 C   s:   z| j | jW S  tk
r4   td| jY nX d S r   )r   Zinspect_imager   r   ro   r   rw   re   re   rf   r   z  s    zService.imagec                 C   s    | j ddj| | jddS )Nr   z{project}_{s.name}z_-)sr   )r   getr   r   lstriprw   re   re   rf   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   )rd   r   re   re   rf   r     s    zService.platformc                 C   sr   | j dd}|stdg S |tjkr.td|S |tjksB| |rLtd|S dd |D }|rhtd|S td|S )	NTr   r   r   recreatec                 S   s   g | ]}|j s|qS re   r   r   re   re   rf   r     s      z,Service.convergence_plan.<locals>.<listcomp>noop)r   rq   rr   rv   r{   r   )rd   Zstrategyr   r   re   re   rf   convergence_plan  s    




zService.convergence_planc              
   C   s   d }z
| j }W n> tk
rL } z td| jt| W Y dS d }~X Y nX d}|D ]R}|| jr|td|j  d}qV|j	
td }||krVtd|j|| d}qV|S )NzService %s has diverged: %sTFz$%s has diverged: Legacy project namez%s has diverged: %s != %s)config_hashro   r   debugr   six	text_typer   r   r   r   r   )rd   r   r   eZhas_divergedr   Zcontainer_config_hashre   re   rf   r     s4    
   z!Service._containers_have_divergedc                    sn     }fdd tfddt||| D  fddfddd\}}| D ]}t|q\|S )	Nc                    s,   | j |dd} s|  r(| |S )NT)r   r   )r   attach_log_streamstart_container)rb   nr   )detachedrd   r   re   rf   create_and_start  s    
z=Service._execute_convergence_create.<locals>.create_and_startc                    s   g | ]}t  j j|qS re   )rp   r   r   )r   indexrw   re   rf   r     s   z7Service._execute_convergence_create.<locals>.<listcomp>c                    s    | j S ra   r   service_name)r   rd   re   rf   r     r   z5Service._execute_convergence_create.<locals>.<lambda>c                    s     | j| jS ra   )get_container_namerb   r   r   rw   re   rf   r     r   ZCreating)r   r-   rangevaluesr+   )rd   r   r   r   ir   errorserrorre   )r   r   rd   r   rf   _execute_convergence_create  s    

	
z#Service._execute_convergence_createc           
         s   |d k	r4t ||kr4||d   |d | } fdd}t||dd d\}}| D ]}	t|	qf|d k	rt ||k r||t |   |S )Nc                    s   j |   dS )N)r   attach_logsr   renew_anonymous_volumes)r   r   r   r   rd   r   r   re   rf   r     s       z7Service._execute_convergence_recreate.<locals>.recreatec                 S   s   | j S ra   r   r   re   re   rf   r     r   z7Service._execute_convergence_recreate.<locals>.<lambda>Z
Recreatingr   r   r-   r   r+   extendr   )
rd   r   r   r   r   r   r   r   r   r   re   r  rf   _execute_convergence_recreate  s&    

  z%Service._execute_convergence_recreatec           	         s   |d k	r4t ||kr4||d  | |d | }|rnt| fdddd d\}}| D ]}t|q`|d k	rt ||k r||t |  | |S )Nc                    s   j |   ddS )NT)r   r   )r   r   r   rd   re   rf   r     r   z4Service._execute_convergence_start.<locals>.<lambda>c                 S   s   | j S ra   r  r   re   re   rf   r     r   ZStartingr  )	rd   r   r   r   r   r   _r   r   re   r  rf   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  rd   r   re   rf   stop_and_remove  s    z+Service._downscale.<locals>.stop_and_removec                 S   s   | j S ra   r  r   re   re   rf   r     r   z$Service._downscale.<locals>.<lambda>zStopping and removingr,   )rd   r   r   r  re   r  rf   r   
  s    zService._downscaleTc	                 C   s  |\}	}
|d k	r|n| j }t|
tdd}
| | |	dkrJ| |||S |sRd }|	dkr|r~|  d }|
D ]}|| qn| |
|||||S |	dkr| |
||||S |	dkr|t	|
kr| |
||||S |
D ]}t
d|j  q|
S td	|	d S )
Nr   r   r   r   Idr   r   z%s is up-to-datezInvalid action: {})r   r   r   r   r   r   Zreset_imager  r   r   r   r   r   	Exceptionr   )rd   Zplanr   r   r   Zscale_overrideZrescaleZreset_container_imager   actionr   r   Zimg_idr   re   re   rf   execute_convergence_plan  s\    
              z Service.execute_convergence_planc                 C   sZ   |j | |d |  | j|s&|nd|jdd}|r@|  |rN| | |  |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.
        r	  NT)r   r   r   )r
  r  Zrename_to_tmp_namer   r   r   r   r   )rd   r   r   r   r   r   Znew_containerre   re   rf   r   G  s    	

zService.recreate_containerc                 C   s,   |d k	r|S t | jd}|d k	r(|S tS )Nstop_grace_period)r3   r   r   r   r  re   re   rf   r  ^  s    zService.stop_timeoutc                 C   s4   |j s0|std|j  |r&|  | |S d S )NzStarting %s)r   r   r   r   r   r   )rd   r   r   r   re   re   rf   r   f  s    z"Service.start_container_if_stoppedc              
   C   sh   |  || z|  W nJ tk
rb } z,d|jkr>td td| j|jf W 5 d }~X Y nX |S )Nz/driver failed programming external connectivityz+Host is already in use by another containerzCannot start service %s: %s)connect_container_to_networksr   r   r   r   warnr+   r   )rd   r   use_network_aliasesr   re   re   rf   r   n  s    

&zService.start_containerc                 C   s   t t| j dd ddS )Nc                 S   s   | d  dpdS )Nr   Zpriorityr   r   )tre   re   rf   r   }  r   z.Service.prioritized_networks.<locals>.<lambda>T)r   reverse)r   r   r   itemsrw   re   re   rf   prioritized_networksx  s     zService.prioritized_networksc                 C   s   | d}| j D ]z\}}||kr@t||r0q| j|j| |rP| ||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)aliasesr  r  r   r  )
r   r  r  short_id_alias_existsr   Z!disconnect_container_from_networkid_get_aliasesZconnect_container_to_network
_get_links)rd   r   r  Zconnected_networksnetworkZnetdefsr  re   re   rf   r    s     

 


z%Service.connect_container_to_networksc                 C   s<   |   D ].}td|j  |j| |d |  qd S )NzRemoving %sr	  )duplicate_containersr   r   r   r
  r  r   )rd   r   r   re   re   rf   remove_duplicate_containers  s    z#Service.remove_duplicate_containersc                 c   sJ   t | jdddd d}t }|D ]"}|j|kr8|V  q"||j q"d S )NTr   c                 S   s
   |  dS )NZCreatedr  r   re   re   rf   r     r   z.Service.duplicate_containers.<locals>.<lambda>r   )r   r   r   r   add)rd   r   numbersr   re   re   rf   r$    s    

zService.duplicate_containersc                 C   s   t |  S ra   )r1   config_dictrw   re   re   rf   r     s    zService.config_hashc                    s<    fdd} j |    jj j jdd  jD dS )Nc                      s*   z   d W S  tk
r$   Y d S X d S Nr  )r   ro   re   rw   re   rf   image_id  s    z%Service.config_dict.<locals>.image_idc                 S   s&   g | ]}t |jtr|jj|jfqS re   )
isinstancesourcer   r   moder   vre   re   rf   r     s    z'Service.config_dict.<locals>.<listcomp>)r   r*  r   netr   r   r^   )r   get_link_namesr   r   r   r   r^   )rd   r*  re   rw   rf   r(    s    zService.config_dictc                 C   sR   | j j}| jj}|  |   |r(|gng  |r6|gng  t| jdi   S )N
depends_on)	r   r   r   get_linked_service_namesget_volumes_from_namesr   r   r   keys)rd   net_namepid_namespacere   re   rf   get_dependency_names  s    zService.get_dependency_namesc                 C   s   | j j}| jj}tdd |  D }|tdd |  D  ||rR|d ini  ||rh|d ini  || jdi  | jdi 	 D ]N\}}|d t
krdd ||< q|d tkrdd ||< qtd	|d q|S )
Nc                 S   s   g | ]}|d fqS ra   re   r   r   re   re   rf   r     s     z2Service.get_dependency_configs.<locals>.<listcomp>c                 S   s   g | ]}|d fqS ra   re   r9  re   re   rf   r     s     r2  Z	conditionc                 S   s   dS )NTre   r   re   re   rf   r     r   z0Service.get_dependency_configs.<locals>.<lambda>c                 S   s   |   S ra   )
is_healthyr:  re   re   rf   r     r   z%depends_on condition "{}" is invalid.)r   r   r   dictr3  r   r4  r   r   r  CONDITION_STARTEDCONDITION_HEALTHYr   r   )rd   r6  r7  ZconfigsZsvcconfigre   re   rf   get_dependency_configs  s,    zService.get_dependency_configsc                 C   s   dd | j D S )Nc                 S   s   g | ]\}}|j qS re   r  )r   rb   r  re   re   rf   r     s     z4Service.get_linked_service_names.<locals>.<listcomp>r   rw   re   re   rf   r3    s    z Service.get_linked_service_namesc                 C   s   dd | j D S )Nc                 S   s   g | ]\}}|j |fqS re   r  )r   rb   aliasre   re   rf   r     s     z*Service.get_link_names.<locals>.<listcomp>rA  rw   re   re   rf   r1    s    zService.get_link_namesc                 C   s   dd | j D S )Nc                 S   s    g | ]}t |jtr|jjqS re   )r+  r,  r   r   )r   r   re   re   rf   r     s      z2Service.get_volumes_from_names.<locals>.<listcomp>r^   rw   re   re   rf   r4    s    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 }|sXd	S t|d	 S )
NTr   Fr   r   r   c                 S   s   g | ]}|j d k	r|j qS ra   r   r   re   re   rf   r     s     
 z2Service._next_container_number.<locals>.<listcomp>r   )	itertoolschain_fetch_containersr   max)rd   r   r   r'  re   re   rf   r     s    	zService._next_container_numberc                    s.    fddt d fdd jjf |D S )Nc                    s0   zt  j| d W S  tk
r*   Y d S X d S r)  )r(   Zfrom_idr   r	   r  rw   re   rf   soft_inspect  s    z/Service._fetch_containers.<locals>.soft_inspectc                    s   g | ]} |qS re   re   r   )rH  re   rf   r   
  s   z-Service._fetch_containers.<locals>.<listcomp>)r   r   r   )rd   Zfetch_optionsre   )rd   rH  rf   rF    s    zService._fetch_containersc                 C   s.   t | jh|r|jhnt B t|ddB S )Nr  re   )r   r   short_idr   r   )rd   r#  r   re   re   rf   r!    s    zService._get_aliasesc                 C   sp   | j s
i S | j | jj }| |i d}|drD|d|d d< |dr`|d|d d< d| jj|iiS )N)ZAliases
IPAMConfigr  rJ  ZIPv4Addressr  ZIPv6AddressZEndpointsConfig)r   r   r   r!  r   )rd   r#  Zendpointre   re   rf   build_default_networking_config  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< qV| jdpg D ](}d|kr|}n|d\}}|||< qdd | D S )Nexternal_links:c                 S   s   g | ]\}}||fqS re   re   )r   container_namerB  re   re   rf   r   =  s   z&Service._get_links.<locals>.<listcomp>)r   r   r   Zname_without_projectr   r   splitr  )rd   link_to_selfr   rb   Z	link_namer   Zexternal_linkre   re   rf   r"  '  s&    
zService._get_linksc                 C   s   dd | j D S )Nc                 S   s   g | ]}t |qS re   )build_volume_from)r   specre   re   rf   r   C  s     z-Service._get_volumes_from.<locals>.<listcomp>rC  rw   re   re   rf   _get_volumes_fromB  s    zService._get_volumes_fromc                    s*  | o
| }|rt  nd }t fddtD }|dg }|| |dsd  j|||d< |dd t	 j
jdrd|krd	|krd
|d kr|d d
}	|	d |d< |	d |d	< t j
jdrd jkr d |d< d|ksd jkrtt|dg  j|d< d|ks&|rBt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                 3   s&   | ]}| j kr| j | fV  qd S ra   r   )r   krw   re   rf   	<genexpr>N  s    
z8Service._get_container_create_options.<locals>.<genexpr>volumesr   detachTz1.23ZhostnameZ
domainname.r   rs   z1.25r  r  portsexposeenvironmentr   r   r   Zhost_confignetworking_config)!r0   r<  r   popr   r   r   r   
setdefaultr   r   r   	partitionr   r   r  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_configrK  format_environment)rd   r   r   r   r   Zadd_config_hashslugr   Zoverride_volumespartsr   r]  re   rw   rf   r   E  s    





  

	
z%Service._get_container_create_optionsc           
      C   s  g }g }d|kr8dd | dD }dd | dD }t|| j dpJg ||\}}|d | tdd |pri D |d< t| jjd	rd
d |D pd |d< nR| j dpg |d< |D ]8}|jr|d 	|j
 q|	|  i |d |j
< q|  }	|	rnt| jjd	rB|dd |	D  |d dd |	D  n,| dpPg |d< |d dd |	D  tt||d< ||fS )NrW  c                 S   s   g | ]}t |tr|qS re   )r+  r   r.  re   re   rf   r     s    
 z;Service._build_container_volume_options.<locals>.<listcomp>c                 S   s   g | ]}t |tr|qS re   )r+  r   r.  re   re   rf   r     s     
 tmpfsr\  c                 s   s   | ]}|j i fV  qd S ra   )internalr.  re   re   rf   rV    s     z:Service._build_container_volume_options.<locals>.<genexpr>z1.30c                 S   s   g | ]}t |qS re   build_mountr.  re   re   rf   r     s     mountsc                 s   s   | ]}|  V  qd S ra   )legacy_reprr.  re   re   rf   rV    s     c                 s   s   | ]}|j i fV  qd S ra   targetr.  re   re   rf   rV    s    c                 S   s   g | ]}t |qS re   rm  r.  re   re   rf   r     s     binds)r   merge_volume_bindingsr   r   r<  r   r   r   Zis_tmpfsappendrr  rp  get_secret_volumesr   r  r   r5   )
rd   r   r   r   container_volumescontainer_mountsrs  affinitymZsecret_volumesre   re   rf   rd    sD      
z'Service._build_container_volume_optionsc           
   ;   C   s\  t | jf|}|dd }t|dd }t|}d }t|dtjrZ|d}d|d< |drxdd |dD nd }d }	d|krt|dt	 }	| j
j| j|d	tt|d
g |d|  |dd| jj|d|d|d|d|d|d|d|d|d|d|dt|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/|d0|d1|d2|d3|d4|d5|d6|d7|d8|d9d:8S );Nloggingblkio_configrI   TrY   c                 S   s   g | ]
}|j qS re   )value)r   ore   re   rf   r     s    z6Service._get_container_host_config.<locals>.<listcomp>r@   )rP  rZ  rs  rV   FrC   rD   rF   rE   rW   rX   r6   r7   rN   rO   rP   ulimitsrG   rL   rJ   r8   r<   rZ   r\   rU   rk  rR   rS   rQ   rH   r]   rK   r9   r:   r_   rA   r?   r[   weightweight_devicedevice_read_bpsdevice_read_iopsdevice_write_bpsdevice_write_iopsro  rB   r;   r=   r>   )8r   Zport_bindingsrs  r^   rV   r   rC   rD   rF   rE   Zrestart_policyrX   r6   r7   rN   rO   rP   r  
log_configrG   rL   r   rY   Zipc_moder8   r<   rZ   r\   rU   rk  rR   rS   rQ   rH   r]   rI   	init_pathrK   r9   r:   	nano_cpusr_   Zcpuset_cpusr?   r[   Zblkio_weightZblkio_weight_devicer  r  r  r  ro  rB   r;   r=   r>   )r<  r   r   convert_blkio_configget_log_configr+  r   Zstring_typesintr&   r   Zcreate_host_configr"  r   rb  rS  r   r-  build_ulimitsr   )
rd   r   r   r   logging_dictr|  r  r  rY   r  re   re   rf   rg    s    



z"Service._get_container_host_configc                    s   dd   fdd| j D S )Nc                 S   sV   | d j }|d kr(dtj| d j}ntj|sBdtj|}td| d |ddS )Nsecretz{}/{}ZbindfileT)rL   )	rr  r   r   ZSECRETS_PATHr,  ospathisabsr   )r  rr  re   re   rf   
build_spec  s    
z.Service.get_secret_volumes.<locals>.build_specc                    s   g | ]} |qS re   re   )r   r  r  re   rf   r   #  s     z.Service.get_secret_volumes.<locals>.<listcomp>)r   rw   re   r  rf   rv    s    	zService.get_secret_volumesc                 C   s   t tjd}|s&tj}td| j  | j	di }|	di 
 }|rR|| |   D ]\}}||| q^t|	d}| jrt| jjdrtd|	s| jnt|
}|j|| j|||||	dd | ||	d	d ||	d
d |	dd |	drt|	dnd |	dd d|r*t|nd i||	d| j	dd | jd}ztt||}W n4 tk
r } zt| t|W 5 d }~X Y nX | j   d }|D ]4}d|krt!"d|	dd}|r|#d}q|d krt| |r|nd|S )NwzBuilding %sr   argscontextr   zEImpossible to perform platform-targeted builds for API version < 1.35
dockerfiler   r#  rr  rZ   rG   memoryrK   )r  tagrmforcermr   nocacher  
cache_fromr   	buildargsr   rr  shmsizerG   container_limitsgziprK   r   streamzSuccessfully built ([0-9a-f]+) r   ZUnknown)$openr  devnullsysstdoutr   r   r   r   r   copyr   rc  r  r_  rewrite_build_pathr   r   r   r   r+   _CLIBuilderr   r   get_cache_fromr2   r   r.   r/   r`   r   r   closeresearchgroup)rd   Zno_cacher   Zforce_rmr  Zbuild_args_overrider  r  r   r   progressZoutput_stream
build_optsZ
build_argsrU  r/  r  ZbuilderZbuild_outputZ
all_eventsr   r*  eventmatchre   re   rf   r   %  sh    





 "


zService.buildc                 C   s&   | dd }|d k	r"dd |D }|S )Nr  c                 S   s   g | ]}|r|qS re   re   )r   r  re   re   rf   r   m  s      z*Service.get_cache_from.<locals>.<listcomp>r  )rd   r  r  re   re   rf   r  j  s    zService.get_cache_fromc                 C   s
   d| j kS )Nr   rT  rw   re   re   rf   r   p  s    zService.can_be_builtc                 C   sF   |s
| j ntdd| j }dt|dt| jdt|r>dndgS )Nz[_-]r  r   TrueFalse)r   r  subr   r"   r#   r   r!   )rd   r   r   Z	proj_namere   re   rf   r   s  s
    
zService.labelsc                 C   s   | j dS )NrN  )r   r   rw   re   re   rf   r   {  s    zService.custom_container_namec                 C   sZ   | j r|d kr| j S t| j|||}dd | jdg D }||krVtd| j||S )Nc                 S   s   g | ]}| d d qS )rM  r   rO  )r   lre   re   rf   r     s     z.Service.get_container_name.<locals>.<listcomp>rL  z5Service {0} has a self-referential external link: {1})r   build_container_namer   r   r   r   r   r   )rd   r   r   ri  rN  Zext_links_originsre   re   rf   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
k
rr   td| j Y dS  tk
r } ztd| j| W Y dS d }~X Y nX d S )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   )rd   Z
image_typer   re   re   rf   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 kr.dS |d }t |tsDdS |\}}|d k	rXdS dS )NZ	publishedFr   T)r+  r<  r   r   tuple)bindingZexternal_bindingsr  Zexternal_bindingZ	host_portre   re   rf   has_host_port  s    

z2Service.specifies_host_port.<locals>.has_host_portc                 3   s   | ]} |V  qd S ra   re   )r   r  r  re   rf   rV    s     z.Service.specifies_host_port.<locals>.<genexpr>rZ  )anyr   r   rw   re   r  rf   r     s    zService.specifies_host_portc           	   
   c   s   z`| j j|f|}|rFttjd}t||D ]
}|V  q.W 5 Q R X nt|tjD ]
}|V  qRW n> tt	fk
r } z|s~ nt
t| W 5 d }~X Y nX d S )Nr  )r   r   r  r  r  r.   r  r  r/   r	   r   r   r   r   )	rd   repoZpull_kwargsr   ignore_pull_failuresoutputr  r  r   re   re   rf   _do_pull  s    zService._do_pullc           	      C   s   d| j krd S t| j d \}}}|p(dd| jd}|sPtd| j|||f  |d rnt| jjdrnt	d| 
||||}|r|S t|S )	Nr   latestT)r  r  r   zPulling %s (%s%s%s)...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  r   Zget_digest_from_pull)	rd   r  r   r  r  r  	separatorkwargsZevent_streamre   re   rf   r     s"    
zService.pullc              
   C   s   d| j ksd| j krd S t| j d \}}}|p2d}td| j|||f  | jj||dd}ztt	|t
jW S  tk
r } z|s ntt| W 5 d }~X Y nX d S )Nr   r   r  zPushing %s (%s%s%s)...T)r  r  )r   r  r   r   r   r   pushr   Zget_digest_from_pushr.   r  r  r/   r   r   r   )rd   Zignore_push_failuresr  r  r  r  r   re   re   rf   r    s    
zService.pushc                 C   s\   d}|   D ]J}|  |d}|dkr6t| jq|dkrDd}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.StatusNZstartingFZ	unhealthy)r   inspectr   r*   r   r)   rI  )rd   r   ZctnrZstatusre   re   rf   r;    s    
zService.is_healthyc                 C   s   | j }d|jkri S t|d|j}|jd ||jd dpBi }ddddd}i }| D ].\}}||krpq^| ||| < |||  < q^|S )	NZproxiesZ_original_base_urlr   Z	FTP_PROXYZ
HTTP_PROXYZHTTPS_PROXYZNO_PROXY)ZftpProxyZ	httpProxyZ
httpsProxyZnoProxy)r   Z_general_configsgetattrZbase_urlr   r  lower)rd   r   Zdocker_hostZproxy_configZ	permittedr   rU  r/  re   re   rf   rc    s*    

 zService._parse_proxy_config)FFNN)r   )N)FNNF)N)NFTNTFF)NFTF)FF)T)T)N)F)N)FN)F)
FFFNNFTFFN)FF)N)FFF)F)Bri   rj   rk   rg   r   r   r   r   r   r   r   r   r~   r   r   r   r|   r   r   rr   rz   r   r   r   r  r   r   r  r   r  r   r   r  r  r%  r$  r   r(  r8  r@  r3  r1  r4  r   rF  r!  rK  r"  rS  r   rd  rg  rv  r   r  r   r   r   r   r  r   r  r   r  r;  rc  re   re   re   rf   r      s   
 

	
;    



        
1  









  
X,
P          
E




r   c                 C   s    |  dj|dpd}| j|kS )Nz&NetworkSettings.Networks.{net}.Aliases)r0  re   )r   r   rI  )r   r#  r  re   re   rf   r     s    
r  c                   @   s,   e Zd Zdd Zedd Zedd ZdS )r   c                 C   s
   || _ d S ra   _mode)rd   r-  re   re   rf   rg   '  s    zPidMode.__init__c                 C   s   | j S ra   r  rw   re   re   rf   r-  *  s    zPidMode.modec                 C   s   d S ra   re   rw   re   re   rf   r   .  s    zPidMode.service_nameN)ri   rj   rk   rg   r|   r-  r   re   re   re   rf   r   &  s
   
r   c                   @   s,   e Zd Zdd Zedd Zedd ZdS )ServicePidModec                 C   s
   || _ d S ra   rm   rn   re   re   rf   rg   4  s    zServicePidMode.__init__c                 C   s   | j jS ra   rb   r   rw   re   re   rf   r   7  s    zServicePidMode.service_namec                 C   s0   | j  }|rd|d j S td| j  d S )N
container:r   z[Service %s is trying to use reuse the PID namespace of another service that is not running.)rb   r   r   r   r   r   rd   r   re   re   rf   r-  ;  s    
zServicePidMode.modeN)ri   rj   rk   rg   r|   r   r-  re   re   re   rf   r  3  s
   
r  c                   @   s   e Zd Zdd ZdS )ContainerPidModec                 C   s   || _ d|j| _d S )Nzcontainer:{})r   r   r   r  rd   r   re   re   rf   rg   I  s    zContainerPidMode.__init__Nrh   re   re   re   rf   r  H  s   r  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   s
   || _ d S ra   r   )rd   r   re   re   rf   rg   S  s    zNetworkMode.__init__c                 C   s   | j S ra   r  rw   re   re   rf   r   V  s    zNetworkMode.id	ri   rj   rk   ry   r   rg   r|   r   r-  re   re   re   rf   r   N  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   s
   || _ d S ra   r  r  re   re   rf   rg   b  s    zContainerNetworkMode.__init__c                 C   s   | j jS ra   r   r   rw   re   re   rf   r   e  s    zContainerNetworkMode.idc                 C   s   d| j j S )Nr  r  rw   re   re   rf   r-  i  s    zContainerNetworkMode.moder  re   re   re   rf   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   s
   || _ d S ra   rm   rn   re   re   rf   rg   q  s    zServiceNetworkMode.__init__c                 C   s   | j jS ra   r  rw   re   re   rf   r   t  s    zServiceNetworkMode.idc                 C   s0   | j  }|rd|d j S td| j  d S )Nr  r   z[Service %s is trying to use reuse the network stack of another service that is not running.)rb   r   r   r   r   r  re   re   rf   r-  z  s    
zServiceNetworkMode.modeN)	ri   rj   rk   ry   rg   r|   r   r   r-  re   re   re   rf   r  n  s   
r  c                 C   s>   |  d|g}|r&|dt|g n|t| d|S )Nz-_runr  )r   r  r4   ru  strjoin)r   rb   r   ri  bitsre   re   rf   r    s
    r  c                 C   sh   d}d}|| kr*|  |d\}}|||fS | d }}|| kr^|  |d\}}d|k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', ':')
    rM  @r   r  /)rsplit)Z	repo_pathZtag_separatorZdigest_separatorr  r  re   re   rf   r    s    


r  c                 C   st   i }t dd | D }|rdt|| ||\}}t| ||j |dd |D  |sV|rdd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 ra   )externalbuild_volume_bindingr   volumere   re   rf   rV    s   z(merge_volume_bindings.<locals>.<genexpr>c                 s   s   | ]}t |V  qd S ra   )r  r  re   re   rf   rV    s    zaffinity:container=)r   get_container_data_volumeswarn_on_masked_volumerb   r   r   r   r   )rW  rk  r   ro  ry  Zvolume_bindingsZold_volumesZ
old_mountsre   re   rf   rt    s$       
rt  c                 C   s  g }|p
g }t dd | dp i D }dd | jd dp@i D }t|| D ]n}|jr^qR|jt| krrqR||j}|sqR|dsqR|jd	d |D krqR|j|d d
}|	| qRd}	|D ]:}|j
dkrq||j}
|
r|
dsq|
d |_d}	q||	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   | ]}|d  |fV  qdS )ZDestinationNre   )r   mountre   re   rf   rV    s   z-get_container_data_volumes.<locals>.<genexpr>ZMountsc                 S   s   g | ]}t |qS re   )r   parser  re   re   rf   r     s   z.get_container_data_volumes.<locals>.<listcomp>ZContainerConfigZVolumesNamec                 S   s   g | ]
}|j qS re   rq  )r   rz  re   re   rf   r     s     )r  Fr  T)r<  r   Zimage_configr   r  rl  r   r5  _replaceru  ru   rr  r,  )r   volumes_optionZtmpfs_optionZmounts_optionrW  rx  Zimage_volumesr  r  Zupdated_mountsZ
ctnr_mountre   re   rf   r    s@    


r  c                 C   s\   t dd |D }| D ]@}|jr|j|kr||j|jkrtdj||j|jd qd S )Nc                 s   s   | ]}|j |jfV  qd S ra   )rl  r  r  re   re   rf   rV    s   z(warn_on_masked_volume.<locals>.<genexpr>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.)rb   r  Z	host_path)r<  r  rl  r   r   r   r   )r  rw  rb   r  re   re   rf   r    s"    r  c                 C   s   | j |  fS ra   )rl  repr)Zvolume_specre   re   rf   r  #  s    r  c                 C   sn   t | jtrL| jjdd}|s4d| j j| jS |d }d|j| jS t | jtrjd| 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   z{}:{}r   N)	r+  r,  r   r   r   r   r   r-  r(   )Zvolume_from_specr   r   re   re   rf   rQ  '  s    
rQ  c                 C   s`   i }| j r<| j| j  D ] \}}|| j kr| j | ||< qtf | j| j| j| j| jd|S )N)ru   rr  r,  rL   consistency)	r   Zoptions_mapru   r  r   rr  r,  rL   r  )Z
mount_specr  ZoptionZsdk_namere   re   rf   rn  9  s    
   rn  c                 C   sj   t | pi }|dd |D  |d k	r4t||t< |d k	rD||t< t|t< |rftd|  ||t	< |S )Nc                 s   s   | ]}| d dV  qdS )r  r   Nr  )r   r   re   re   rf   rV  K  s     z)build_container_labels.<locals>.<genexpr>zAdded config hash: %s)
r<  r   r  r    r$   r   r%   r   r   r   )Zlabel_optionsZservice_labelsr   r   ri  r   re   re   rf   re  I  s    re  c                 C   sj   | sd S g }t | D ]N\}}t|t jr>||||d qt|trd|i}|| || q|S )N)r   ZsoftZhardr   )r   Z	iteritemsr+  Zinteger_typesru  r<  r   )Zulimit_configr  Z
limit_nameZsoft_hard_valuesZulimit_dictre   re   rf   r  \  s    

r  c                 C   s4   | r|  ddnd}| r$|  dd nd }t||dS )NZdriverr  r   )ru   r?  )r   r
   )r  rM   Zlog_optionsre   re   rf   r  k  s    r  c                    s   dd   fdd|   D S )Nc                 S   s0   |d kr| S t |tjr"|d}dj| |dS )Nzutf-8z{key}={value}r   r}  )r+  r   Zbinary_typedecoder   r  re   re   rf   
format_envv  s
    
z&format_environment.<locals>.format_envc                    s   g | ]} | qS re   re   )r   itemr  re   rf   r   }  s     z&format_environment.<locals>.<listcomp>)r  )r\  re   r  rf   rh  u  s    rh  c                 C   s6   g }| D ](}t |tr&||  q|| q|S ra   )r+  r   ru  rp  )rZ  r   portre   re   rf   rb    s    
rb  c                 C   s`   g }| | dg  }|D ]B}t|\}}|D ],}t|}d|krNt|d}|| q,q|S )Nr[  r  )r   r   r  r  rO  ru  )Zcontainer_portsr   rZ  Z	all_portsZ
port_rangeZinternal_ranger  r  re   re   rf   ra    s    ra  c                 C   sl   i }| d kr|S |  d|d< dD ]D}|| kr0q"g }| | D ] }|tdd | D  q<|||< q"|S )Nr  )r  r  r  r  r  c                 S   s   g | ]\}}|  |fqS re   )
capitalize)r   rU  r/  re   re   rf   r     s     z(convert_blkio_config.<locals>.<listcomp>)r   ru  r<  r  )r|  r   ZfieldZarrr  re   re   rf   r    s    
r  c                 C   s>   t jsts| d} tr:t| s:| ts:ttj	|  } | S )Nutf8)
r   ZPY3r   encoder   
startswithr'   r  r  normpath)r  re   re   rf   r    s
    

r  c                   @   s   e Zd Zdd ZdddZdS )	r  c                 C   s
   || _ d S ra   )	_progress)rd   r  re   re   rf   rg     s    z_CLIBuilder.__init__NFTc           $   	   c   sz  |rt j||}t }t }|d| |d| |d| |	d| |d|
d |	d| |d| j |	d	|
 |d
| |d| |d| ||g}d}d}tj|tjddH} | j }!|!sqtjrt|}|!|rd}td|!iV  qW 5 Q R X t| }"|" }!|!dd  }#W 5 Q R X t | |svtdd||#iV  dS )a  
        Args:
            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.
        Returns:
            A generator for the build output.
        z--build-argz--cache-fromz--filez
--force-rmz--memoryr  z
--no-cachez
--progressz--pullz--tagz--targetz	--iidfilezSuccessfully built FT)r  Zuniversal_newlinesr  rM  r   z{}{}
N)r  r  r  tempfileZmktemp_CommandBuilder
add_paramsadd_listadd_argadd_flagr   r  r   
subprocessPopenPIPEr  readliner   PY2r  r  jsondumpsr  rO  stripr   r   )$rd   r  r  r   Zfileobjr  r  r   Zcustom_contextencodingr   r  r  r  r  r  r  r  r   r  rr  r   ZsquashrG   r   rK   Zuse_config_proxyZiidfileZcommand_builderr  Z
magic_wordZappearplinefr*  re   re   rf   r     sB    =


z_CLIBuilder.build)NFNFFNFNFFNNFNFNNNNNNNNNT)ri   rj   rk   rg   r   re   re   re   rf   r    s2                                         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 )NZdockerr   _argsrw   re   re   rf   rg   &  s    z_CommandBuilder.__init__c                 C   s   |r| j |t|g d S ra   )r  r  r  )rd   r   r}  re   re   rf   r  )  s    z_CommandBuilder.add_argc                 C   s   |r| j |g d S ra   r  r  )rd   r   flagre   re   rf   r   -  s    z_CommandBuilder.add_flagc                 C   s2   |r.|  D ] \}}| j|d||g qd S )Nz{}={})r  r  r  r   )rd   r   Zparamsr   valre   re   rf   r  1  s    z_CommandBuilder.add_paramsc                 C   s"   |r|D ]}| j ||g qd S ra   r  )rd   r   r   r  re   re   rf   r  6  s    z_CommandBuilder.add_listc                 C   s
   | j | S ra   r  )rd   r  re   re   rf   r   ;  s    z_CommandBuilder.buildN)	ri   rj   rk   rg   r  r   r  r  r   re   re   re   rf   r  %  s   r  )N)zZ
__future__r   r   rD  r  r{  r  r  r  r  collectionsr   r   operatorr   enumr   Zdocker.errorsr   r   r	   Zdocker.typesr
   r   Zdocker.utilsr   r   Zdocker.utils.portsr   r   Zdocker.utils.utilsr   r  r   r   r   r?  r   r   r   r   Zconfig.errorsr   Zconfig.typesr   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r   r(   r   r)   r*   r+   Zparallelr-   r.   r/   Zutilsr0   r1   r2   r3   r4   r5   r  Zsubprocess32r  Z	getLoggerri   r   rf  r=  r>  r  r`   rl   ro   rp   rq   uniqueEnumrr   r}   r   objectr   r  r   r  r  r   r  r  r  r  rt  r  r  r  rQ  rn  re  r  r  rh  rb  ra  r  r  r  r  re   re   re   rf   <module>   s4  

/

        |
?

n