a
   3;5"Z                   @   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mZ d dlm	Z	 d dl
mZ d dl
mZ d dlZd dlmZ ddlmZ d	d
lmZ d	dlmZ d	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'l6m8Z8 dd(l6m9Z9 dd)l6m:Z: dd*l6m;Z; dd+l6m<Z< dd,l6m=Z= dd-l6m>Z> dd.l6m?Z? dd/l6m@Z@ dd0l6mAZA dd1l6mBZB dd2l6mCZC dd3l6mDZD dd4l6mEZE g d5ZFeFg d6 ZGd7ZHd8d9gZId:ZJeKeLZMG d;d< d<ed=d>ZNG d?d@ d@edAdBZOG dCdD dDedEdFZPG dGdH dHedIdJZQddKdLZRdMdN ZSdOdP ZTdQdR ZUdSdT ZVdUdV ZWddXdYZXddZd[ZYd\d] ZZd^d_ Z[dd`daZ\dbdc Z]ddde Z^ddfdgZ_G dhdi diZ`ddjdkZadldm Zbdndo Zcdpdq Zddrds Zedtdu Zfdvdw Zgdxdy Zhdzd{ Zid|d} Zjd~d ZkdddZldd Zmdd ZnG dd deoZpdd Zqdd Zrdd Zsdd Ztdd Zudd Zvdd Zwdd Zxdd Zydd Zzdd Z{dd Z|dd Z}dd Z~dd Zdd Ze ee!dZe ee!dZe eedZe edd dZe eedZe edd dZdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd ZddĄ ZddƄ ZddȄ Zddʄ Zdd̄ Zdd΄ ZddЄ Zdd҄ ZddԄ Zddք Zddd؄ZdS )    N)
namedtuple)chain)
attrgetter)
itemgetter)cached_property   )types   )COMPOSE_SPEC)COMPOSEFILE_V1)build_string_dict	json_hash)parse_bytes)parse_nanoseconds_int)
splitdrive)ComposeVersion)env_vars_from_file)Environment)	split_env)CircularReference)ComposeFileNotFound)ConfigurationError)DuplicateOverrideFileFound)VERSION_EXPLANATION)!interpolate_environment_variables)$get_container_name_from_network_mode)"get_service_name_from_network_mode)sort_service_dicts)	MountSpec)parse_extra_hosts)parse_restart_spec)SecurityOpt)ServiceLink)ServicePort)VolumeFromSpec)
VolumeSpec)match_named_volumes)validate_against_config_schema)validate_config_section)validate_cpu)validate_credential_spec)validate_depends_on)validate_extends_file_path)validate_healthcheck)validate_ipc_mode)validate_links)validate_network_mode)validate_pid_mode)validate_service_constraints)validate_top_level_object)validate_ulimits)<cap_addcap_dropZcgroup_parentZcommand	cpu_countZcpu_percentZ
cpu_periodZ	cpu_quotaZcpu_rt_periodZcpu_rt_runtimeZ
cpu_sharescpusZcpusetdetachdevice_cgroup_rulesdevicesdns
dns_searchZdns_optZ
domainnameZ
entrypointenv_fileenvironmentextra_hostsZ	group_addhostnamehealthcheckimageZipc	isolationlabelslinksZmac_addressZ	mem_limitZmem_reservationZmemswap_limitZmem_swappinessnetZoom_score_adjZoom_kill_disablepidportsZ
privilegedZ	read_onlyrestartZruntimesecretssecurity_optshm_sizeZ
pids_limitZ
stdin_openZstop_signalsysctlsZttyuserZuserns_modevolume_drivervolumesvolumes_fromworking_dir)blkio_configbuildcontainer_nameZcredential_spec
dockerfileinit
log_driverlog_optloggingnetwork_modeplatformprofilesZscaleZstop_grace_period)zhttp://zhttps://zgit://zgithub.com/zgit@zdocker-compose.ymlzdocker-compose.yaml)zdocker-compose.override.ymlzdocker-compose.override.yamlc                       s"   e Zd ZdZd fdd	Z  ZS )ConfigDetailsac  
    :param working_dir: the directory to use for relative paths in the config
    :type  working_dir: string
    :param config_files: list of configuration files to load
    :type  config_files: list of :class:`ConfigFile`
    :param environment: computed environment values for this project
    :type  environment: :class:`environment.Environment`
     Nc                    s$   |d u rt |}t | |||S N)r   Zfrom_env_filesuper__new__)clsrT   config_filesr@   	__class__ 9/usr/lib/python3.9/site-packages/compose/config/config.pyrc      s
    
zConfigDetails.__new__)N)__name__
__module____qualname____doc__rc   __classcell__rh   rh   rf   ri   r`      s   r`   Z_ConfigDetailsz$working_dir config_files environmentc                   @   sd   e Zd ZdZedd Zedd Zedd Zdd	 Z	d
d Z
dd Zdd Zdd Zdd ZdS )
ConfigFilez
    :param filename: filename of the config file
    :type  filename: string
    :param config: contents of the config file
    :type  config: :class:`dict`
    c                 C   s   | |t |S ra   )	load_yaml)rd   filenamerh   rh   ri   from_filename   s    zConfigFile.from_filenamec                 C   s.   | j dd }t|trtS |r(t|S | jS )Nversion)configget
isinstancedictV1r   rs   )selfrs   rh   rh   ri   config_version   s    
zConfigFile.config_versionc                 C   s  | j dd }|s| j dd }| j dd }| j dd }|sH|sH|rndD ]}t| j| j |i | qLtS t| j| j d tS t|trt	d
| jt tS t|tstd
| jt|trtd}||std	
|| j|d
rtd
| jttS )Nrs   servicesnetworksrR   )r{   r|   rR   zUnexpected type for "version" key in "{}". Assuming "version" is the name of a service, and defaulting to Compose file version {}.z3Version in "{}" is invalid - it should be a string.z^[1-3]+(\.\d+)?$z Version "{}" in "{}" is invalid.1zVersion in "{}" is invalid. {})rt   ru   r)   rq   VERSIONrx   rv   rw   logwarningformatstrr   recompilematch
startswithr   )ry   rs   r{   r|   rR   sectionZversion_patternrh   rh   ri   rs      sR    





zConfigFile.versionc                 C   s   |   | S ra   get_service_dicts)ry   namerh   rh   ri   get_service   s    zConfigFile.get_servicec                 C   s   | j tkr| jS | jdi S )Nr{   rs   rx   rt   ru   ry   rh   rh   ri   r      s    
zConfigFile.get_service_dictsc                 C   s   | j tkri S | jdi S )NrR   r   r   rh   rh   ri   get_volumes   s    zConfigFile.get_volumesc                 C   s   | j tkri S | jdi S )Nr|   r   r   rh   rh   ri   get_networks   s    zConfigFile.get_networksc                 C   s   | j tkri S | jdi S )NrL   r   r   rh   rh   ri   get_secrets   s    zConfigFile.get_secretsc                 C   s   | j tkri S | jdi S )Nconfigsr   r   rh   rh   ri   get_configs  s    zConfigFile.get_configsN)rj   rk   rl   rm   classmethodrr   r   rz   rs   r   r   r   r   r   r   rh   rh   rh   ri   ro      s   


-ro   Z_ConfigFilezfilename configc                   @   s   e Zd ZdZdS )Configa  
    :param config_version: configuration file version
    :type  config_version: int
    :param version: configuration version
    :type  version: int
    :param services: List of service description dictionaries
    :type  services: :class:`list`
    :param volumes: Dictionary mapping volume names to description dictionaries
    :type  volumes: :class:`dict`
    :param networks: Dictionary mapping network names to description dictionaries
    :type  networks: :class:`dict`
    :param secrets: Dictionary mapping secret names to description dictionaries
    :type secrets: :class:`dict`
    :param configs: Dictionary mapping config names to description dictionaries
    :type configs: :class:`dict`
    N)rj   rk   rl   rm   rh   rh   rh   ri   r     s   r   Z_Configz@config_version version services volumes networks secrets configsc                   @   s   e Zd Zedd ZdS )ServiceConfigc                 C   s2   |st d| tj||r(tj|n|||S )Nz!No working_dir for ServiceConfig.)
ValueErrorospathabspath)rd   rT   rq   r   rt   rh   rh   ri   with_abs_paths  s    
zServiceConfig.with_abs_pathsN)rj   rk   rl   r   r   rh   rh   rh   ri   r     s   r   Z_ServiceConfigz working_dir filename name configc                    s   |dgkr:t |rtj|nt td ttj	g|S |rR fdd|D }nt
 }tdd| t |rz|ntj|d dd |D |S )N-c                    s   g | ]}t j |qS rh   )r   r   join.0fbase_dirrh   ri   
<listcomp>1      zfind.<locals>.<listcomp>zUsing configuration files: {},r   c                 S   s   g | ]}t |qS rh   )ro   rr   r   rh   rh   ri   r   8  r   )r`   r   r   r   getcwdro   yaml	safe_loadsysstdinget_default_config_filesr   debugr   r   dirname)r   	filenamesr@   Zoverride_dirrh   r   ri   find(  s    
r   c                 C   sV   | d }t | | dd  D ]4}t | |j|jkrtd|j|j|j|jqd S )Nr   r   zTVersion mismatch: file {} specifies version {} but extension file {} uses version {})r4   rs   r   r   rq   )re   	main_fileZ	next_filerh   rh   ri   validate_config_version=  s    r   c                 C   sd   t t| \}}|stt|d }t|dkrLtdd| td| tj||gt	| S )Nr   r   z4Found multiple config files with supported names: %s, z	Using %s
)
find_candidates_in_parent_dirsSUPPORTED_FILENAMESr   lenr   r   r   r   r   get_default_override_file)r   
candidatesr   winnerrh   rh   ri   r   N  s    r   c                    s*    fddt D }t|dkr&t||S )Nc                    s0   g | ](}t jt j |rt j |qS rh   r   r   existsr   )r   Zoverride_filenamer   rh   ri   r   ^  s   z-get_default_override_file.<locals>.<listcomp>r   )DEFAULT_OVERRIDE_FILENAMESr   r   )r   Zoverride_files_in_pathrh   r   ri   r   ]  s    
r   c                    sN    fdd| D }|sFt j d}t j|t j krFt| |S | fS )z
    Given a directory path to start, looks for filenames in the
    directory, and then each parent directory successively,
    until found.

    Returns tuple (candidates, path).
    c                    s&   g | ]}t jt j |r|qS rh   r   )r   rq   r   rh   ri   r   n  s   z2find_candidates_in_parent_dirs.<locals>.<listcomp>z..)r   r   r   r   r   )r   r   r   Z
parent_dirrh   r   ri   r   f  s    
r   c                    sJ   d}d  fdd| D }|rFt |jdtdd |D  d d S )	NzSome services ({services}) use the '{key}' key, which will be ignored. Compose does not support '{key}' configuration - use `docker stack deploy` to deploy to a swarm.r   c                    s   g | ]}|  r|qS rh   )ru   r   skeyrh   ri   r     r   z+check_swarm_only_config.<locals>.<listcomp>r   c                 s   s   | ]}|d  V  qdS )r   Nrh   r   rh   rh   ri   	<genexpr>  r   z*check_swarm_only_config.<locals>.<genexpr>)r{   r   )r   r   r   r   sorted)service_dictsZwarning_templater{   rh   r   ri   check_swarm_only_configy  s    r   Tc           
         s   t  j  fdd jD } j|d  jd }t jdd}t jdd}t jd	d
 j}t jdd j}t |d}|jtkr|D ]}	t|	| qt	| t
|j|j|||||S )a  Load the configuration from a working directory and a list of
    configuration files.  Files are loaded in order, and merged on top
    of each other to create the final configuration.

    Return a fully interpolated, extended and validated configuration.
    c                    s   g | ]}t | jd qS )interpolate)process_config_filer@   )r   config_fileconfig_detailsr   rh   ri   r     s   zload.<locals>.<listcomp>)re   r   r   Volumer   Networkr   ZSecretr   r   r   )r   re   _replaceload_mappingrT   load_servicesrs   rx   r'   r   r   rz   )
r   r   Zprocessed_filesr   rR   r|   rL   r   r   service_dictrh   r   ri   load  s4    	




r   c           
      C   s   i }| D ]}t ||  D ]\}}|p*i ||< |s6q|d}|rt||||j t|trn|d|d< n|ds||d< d|v rt|d |d< d|v rt||d |d< d|v rt	|d |d< t
||}	|	r|	|d d< qq|S )Nexternalr   rF   filedriver_optsdevice)getattritemsru   validate_externalrs   rv   rw   parse_labelsexpand_pathr   format_device_option)
re   Zget_funcentity_typerT   mappingr   r   rt   r   r   rh   rh   ri   r     s2    



r   c                 C   sl   | dkrd S | dd}|dkr$d S |d  d}|d  d}|rh|dkrh|rhtjtj|}|S d S )Nr   driverlocalr   or   bind)ru   r   r   r   
expanduser)r   rt   r   r   r   fullpathrh   rh   ri   r     s    r   c              
   C   sN   |  D ]@}| dkr|dkrq|dvrtd| |ddd |D qd S )Nr   r   )r   r   zD{} {} declared as external but specifies additional attributes ({}).r   c                 s   s   | ]}|d kr|V  qdS )r   Nrh   r   krh   rh   ri   r     r   z$validate_external.<locals>.<genexpr>)keysr   r   r   )r   r   rt   rs   r   rh   rh   ri   r     s    r   c                    sL   fdd  fdd}fdd}dd j D }t||}||S )	Nc                    s`   t  jj| |}t| jd}t| }|j|d}t	|| t
||j j}|S )Nr@   rt   )r   r   rT   rq   ServiceExtendsResolverr@   process_servicerunr   validate_servicefinalize_servicers   )service_namer   service_namesservice_configresolver)r   r   r   rh   ri   build_service  s(    z$load_services.<locals>.build_servicec                    s$   |    t fdd|  D S )Nc                    s   g | ]\}} ||qS rh   rh   )r   r   r   )r   r   rh   ri   r     s   z9load_services.<locals>.build_services.<locals>.<listcomp>)r   r   r   )r   )r   )r   ri   build_services  s    z%load_services.<locals>.build_servicesc                    s&   t  t B } fdd|D S )Nc              	      s,   i | ]$}|t  |i |i jqS rh   )merge_service_dicts_from_filesru   rs   )r   r   )baser   overriderh   ri   
<dictcomp>  s   

z9load_services.<locals>.merge_services.<locals>.<dictcomp>)set)r   r   Zall_service_names)r   r   r   ri   merge_services  s    z%load_services.<locals>.merge_servicesc                 S   s   g | ]}|  qS rh   r   )r   r   rh   rh   ri   r     s   z!load_services.<locals>.<listcomp>)re   	functoolsreduce)r   r   r   r   r   Zservice_configsr   rh   )r   r   r   r   ri   r     s    
r   c                 C   s   t | j|||S ra   )r   rs   )r   rt   r   r@   rh   rh   ri   interpolate_config_section  s    r   c                 C   s*   t | j|| |r"t| j|||S |S d S ra   )r)   rq   r   rs   )r   rt   r   r@   r   rh   rh   ri   process_config_section(  s    r   c                 C   s   t | |  d||}| jtkrt| j}||d< t | |  d|||d< t | |  d|||d< t | |  d|||d< t | | 	 d	|||d
< n|}| j
|d} t| | j |r||vrtd|| j| S )Nservicer{   volumerR   networkr|   ZsecretrL   rt   r   r   3Cannot extend service '{}' in {}: Service not found)r   r   rs   rx   rw   rt   r   r   r   r   r   r(   r   r   rq   )r   r@   r   r   r{   Zprocessed_configrh   rh   ri   r   5  s`    


r   c                   @   sJ   e Zd ZdddZedd Zdd Zdd	 Zd
d Zdd Z	dd Z
dS )r   Nc                 C   s(   || _ |j| _|pg | _|| _|| _d S ra   )r   rT   already_seenr   r@   )ry   r   r   r@   r  rh   rh   ri   __init__l  s
    
zServiceExtendsResolver.__init__c                 C   s   | j j| j jfS ra   )r   rq   r   r   rh   rh   ri   	signatures  s    z ServiceExtendsResolver.signaturec                 C   s"   | j | jv rt| j| j g d S ra   )r  r  r   r   rh   rh   ri   detect_cyclew  s    z#ServiceExtendsResolver.detect_cyclec                 C   s6   |    d| jjv r0| j|   }| jj|dS | jS )Nextendsr   )r  r   rt   resolve_extendsvalidate_and_construct_extendsr   )ry   r   rh   rh   ri   r   {  s
    zServiceExtendsResolver.runc                 C   s   | j jd }t|tsd|i}| |}|d }|tj| jj	krzz| j
|}W q tyv   td||Y q0 n2t|}t| j|g t|| j|d}|
|}|||fS )Nr  r   r  )r   )r   rt   rv   rw   get_extended_config_pathr   r   r   r   rq   r   KeyErrorr   r   ro   rr   r   r   r@   )ry   r  Zconfig_pathr   r   Zextends_fileZextended_filerh   rh   ri   r    s*    



z5ServiceExtendsResolver.validate_and_construct_extendsc                 C   sb   t ttj||||| j| j| jg | j	d}|
 }t|}t||| t|| jj| jjS )N)r  r@   )r   r   r   r   r   r   r   r  r  r@   r   r   validate_extended_service_dictmerge_service_dictsr   rt   rs   )ry   Zextended_config_pathr   r   r   r   Zother_service_dictrh   rh   ri   r    s.    
z&ServiceExtendsResolver.resolve_extendsc                 C   s4   | j j}t| j j|| d|v r0t| j|d S |S )zService we are extending either has a value for 'file' set, which we
        need to obtain a full path too or we are extending from a service
        defined in our own file.
        r   )r   rq   r-   r   r   rT   )ry   Zextends_optionsrq   rh   rh   ri   r	    s    z/ServiceExtendsResolver.get_extended_config_path)N)rj   rk   rl   r  propertyr  r  r   r  r  r	  rh   rh   rh   ri   r   k  s   

	r   c                    sT   i }|  dg D ]}|t|| q|t|  d t fdd| D S )zjUnpack any environment variables from an env_file, if set.
    Interpolate environment values if set.
    r?   r@   c                 3   s   | ]\}}t || V  qd S ra   resolve_env_varr   r   vr   rh   ri   r     r   z&resolve_environment.<locals>.<genexpr>)ru   updater   parse_environmentrw   r   )r   r@   r   envr?   rh   r   ri   resolve_environment  s
    r  c                    s"   t | }t fdd| D S )Nc                 3   s   | ]\}}t || V  qd S ra   r  r  r   rh   ri   r     r   z%resolve_build_args.<locals>.<genexpr>)parse_build_argumentsrw   r   )Z	buildargsr@   argsrh   r   ri   resolve_build_args  s    r  c                 C   s   d ||}d| v r td| d| v r4td| d| v rTt| d rTtd| d| v rtt| d rttd	| d
| v rtd| d S )Nz!Cannot extend service '{}' in {}:rG   z+%s services with 'links' cannot be extendedrS   z2%s services with 'volumes_from' cannot be extendedrH   z4%s services with 'net: container' cannot be extendedr]   z;%s services with 'network_mode: service' cannot be extended
depends_onz0%s services with 'depends_on' cannot be extended)r   r   r   r   )r   rq   r   Zerror_prefixrh   rh   ri   r    s.    r  c                 C   s   dd }| j | j }}t||| | r0t| t|  t|  t| | t| | t| | t	| | t
| | t|  t|  |dst|rtdj|dd S )Nc                  S   s*   t jdd  } d| v rdS d| v r&dS dS )Nr   ZpullFz
--no-buildT)r   argv)r  rh   rh   ri   build_image  s    z%validate_service.<locals>.build_imagerD   zService '{name}' contains uppercase characters which are not valid as part of an image name. Either use a lowercase service name or use the `image` field to set a custom name for the service image.r   )rt   r   r3   validate_pathsr*   r5   r/   r1   r2   r,   r0   r.   r+   ru   has_uppercaser   r   )r   r   r   r  r   r   rh   rh   ri   r     s(    





r   c                    s   | j  t| j}d|v r6 fddt|d D |d< d|v rHt|  d|v rl|dd u rlt ||d< d|v rtt|d |d< d|v rt	|d |d< t
|}d	D ]}||v rt|| ||< qtttt|}|S )
Nr?   c                    s   g | ]}t  |qS rh   )r   )r   r   rT   rh   ri   r     s   z#process_service.<locals>.<listcomp>rV   rR   rQ   rO   rF   )r=   r>   tmpfs)rT   rw   rt   to_listprocess_build_sectionru   resolve_volume_pathsr   parse_sysctlsr   process_depends_onprocess_security_optprocess_blkio_configprocess_portsprocess_healthcheck)r   r   fieldrh   r  ri   r     s,    




r   c                 C   s   t | d tr"t|| d | d< n\t | d tr~d| d v rZ| d d }t||| d d< d| d v r~t| d d | d d< d S )NrV   contextrF   )rv   r   resolve_build_pathrw   r   )r   rT   r   rh   rh   ri   r"  7  s    r"  c                 C   sP   d| vr| S g }| d D ]*}t |tr2|| q|t| q|| d< | S )NrJ   )rv   r$   appendextendparse)r   rJ   Zport_definitionrh   rh   ri   r(  B  s    
r(  c                 C   s0   d| v r,t | d ts,dd | d D | d< | S )Nr  c                 S   s   i | ]}|d diqS )	conditionservice_startedrh   )r   Zsvcrh   rh   ri   r   R  s   z&process_depends_on.<locals>.<dictcomp>)rv   rw   r   rh   rh   ri   r%  P  s
    
r%  c                 C   s   |  ds| S dD ]X}|| d v r| d  |g D ]6}| dd}t||d< |d d u r2td|q2qdD ]f}|| d v rp| d  |g D ]D}zt| dd|d< W q ty   td| dY q0 qqp| S )NrU   )device_read_bpsdevice_write_bpsrater   z$Invalid format for bytes value: "{}")device_read_iopsdevice_write_iopsz5Invalid IOPS value: "{}". Must be a positive integer.)ru   r   r   r   intr   )r   r*  r  r5  rh   rh   ri   r'  X  s&    
r'  c                 C   sb   d| vr| S | d }d|v r,|d= dg|d< dD ],}||vs0t || trLq0t|| ||< q0| S )NrC   disableZNONEtest)intervaltimeoutZstart_period)rv   r8  r   )r   Zhcr*  rh   rh   ri   r)  q  s    
r)  c           	      C   s   d| v rg }| d}| d}| d D ]8}t|trL|t||| q(|t||| q(g }dd |D }|D ]0}ttt	d|
|jdkrx||  qx|rtdd	| || d< | S )
NrR   ZCOMPOSE_CONVERT_WINDOWS_PATHSZCOMPOSE_FORCE_WINDOWS_HOSTc                 S   s"   g | ]}t |tr| n|qS rh   )rv   r   Zas_volume_specr   r  rh   rh   ri   r     r   z,finalize_service_volumes.<locals>.<listcomp>internalr   zDuplicate mount points: [%s]r   )Zget_booleanrv   rw   r-  r   r/  r&   listmapr   countr>  reprr   r   )	r   r@   Zfinalized_volumes	normalizeZwin_hostr  Zduplicate_mountsZmountsZmountrh   rh   ri   finalize_service_volumes  s&    


rD  c                    s0  t | j}d|v sd|v r6t||||d< |dd  d|v rZ fdd|d D |d< t||}d|v r|d}t|}|r| v rd||d< n||d< d	|v rt|d	 |d	< d
|v rt|d
 |d
< d|v rdd |d D |d< d|v rdd |d D |d< t	|| j
| | j|d< t|S )Nr@   r?   rS   c                    s   g | ]}t | qS rh   )r%   r/  )r   Zvfr   rs   rh   ri   r     s   z$finalize_service.<locals>.<listcomp>rH   z
service:{}r]   r|   rK   rL   c                 S   s   g | ]}t j|qS rh   )r   ServiceSecretr/  r   rh   rh   ri   r     s   r   c                 S   s   g | ]}t j|qS rh   )r   r   r/  )r   crh   rh   ri   r     s   r   )rw   rt   r  poprD  r   r   parse_networksr!   normalize_buildrT   r   normalize_v1_service_format)r   r   rs   r@   r   r   r]   rW   rh   rE  ri   r     s<    







r   c                 C   s   d| v sd| v r\d| vr i | d< d| v r>| d | d d< | d= d| v r\| d | d d< | d= d| v r|  di | d< | d d| di | S )NrZ   r[   r\   r   optionsrX   rV   )ru   r  rH  r2  rh   rh   ri   rK    s    
rK  c                 C   s:   t | ||}d|v r"|d |d< nd| v r6| d |d< |S )zWhen merging services from multiple files we need to merge the `extends`
    field. This is not handled by `merge_service_dicts()` which is used to
    perform the `extends`.
    r  )r  )r   r   rs   Znew_servicerh   rh   ri   r     s    r   c                   @   sD   e Zd ZdZdd Zdd ZdddZdd	d
Zdd Zdd Z	dS )	MergeDictz>A dict-like object responsible for merging two dicts into one.c                 C   s   || _ || _d S ra   r   )ry   r   r   rh   rh   ri   r    s    zMergeDict.__init__c                 C   s   || j v p|| jv S ra   r   ry   r*  rh   rh   ri   needs_merge  s    zMergeDict.needs_mergeNc                 C   s4   |  |sd S || j||| j||| |< d S ra   )rO  r   ru   r   )ry   r*  Z
merge_funcdefaultrh   rh   ri   merge_field  s    
zMergeDict.merge_fieldc                 C   sP   |  |sd S |d u rdd }|| j|| |< | | || j| d S )Nc                 S   s   | pi S ra   rh   mrh   rh   ri   
parse_func  s    z+MergeDict.merge_mapping.<locals>.parse_func)rO  r   ru   r  r   )ry   r*  rT  rh   rh   ri   merge_mapping  s    
zMergeDict.merge_mappingc                    sb    fdd}|  |sd S || j|g }||| j|g  dd t| D | |< d S )Nc                    s   t  fdd| D dS )Nc                 3   s   | ]} |V  qd S ra   rh   r   itemrT  rh   ri   r     r   zHMergeDict.merge_sequence.<locals>.parse_sequence_func.<locals>.<genexpr>rQ  
to_mapping)seqrX  rh   ri   parse_sequence_func
  s    z5MergeDict.merge_sequence.<locals>.parse_sequence_funcc                 S   s   g | ]}|  qS rh   )rB  rV  rh   rh   ri   r     r   z,MergeDict.merge_sequence.<locals>.<listcomp>)rO  r   ru   r  r   r   values)ry   r*  rT  r\  mergedrh   rX  ri   merge_sequence	  s    
zMergeDict.merge_sequencec                 C   s(   |  |r$| j|| j|| |< d S ra   )rO  r   ru   r   rN  rh   rh   ri   merge_scalar  s    
zMergeDict.merge_scalar)N)N)
rj   rk   rl   rm   r  rO  rQ  rU  r_  r`  rh   rh   rh   ri   rM    s   

rM  c                 C   s  t | |}|dt |dt |dt |dt |dt |dt |dtj	 |dt
jj	 |d	t
jj	 |d
t
jj	 |dt |jdti d dD ]}||t qdD ]}|j|tg d qdD ]}||t q|jdti d t|| | |jdti d |jdti d |jdti d ttt| D ]}|| qN|tkrxt|| | n|drt|| ||d< t |S )Nr@   rF   ZulimitsrO   r  Zstorage_optrG   rL   r   rM   rA   r|   rP  )rR   r<   )r6   r7   ZexposeZexternal_linksrS   r;   r_   )r=   r>   r?   r   r\   rU   rC   ZdeployrV   )!rM  rU  r  r   parse_flat_dictr$  parse_depends_onr_  r#   r/  r   rF  r   r"   r    rQ  merge_networksmerge_path_mappingsmerge_unique_items_listsmerge_list_or_stringmerge_loggingmerge_portsmerge_blkio_configmerge_healthchecksmerge_deployr   ALLOWED_KEYSr`  rx   legacy_v1_merge_image_or_buildrO  merge_buildrw   )r   r   rs   mdr*  rh   rh   ri   r    s>    

r  c                 C   s.   dd |D }dd | D } t tt| |S )Nc                 s   s   | ]}t |V  qd S ra   r   r   r   rh   rh   ri   r   G  r   z+merge_unique_items_lists.<locals>.<genexpr>c                 s   s   | ]}t |V  qd S ra   rq  r   brh   rh   ri   r   H  r   )r   r   r   r   rh   rh   ri   rf  F  s    rf  c                 C   s(   | ddu r|S |  }|| |S )NZdisabledT)ru   copyr  r   r   resultrh   rh   ri   rk  L  s
    
rk  c                 C   sj   dd }d}|  |sd S || j|g }||| j|g  dd t| tddD | |< d S )Nc                 S   s   dd | D }t |dS )Nc                 S   s    g | ]}t |D ]}|qqS rh   )r$   r/  )r   rW  r   rh   rh   ri   r   V  r   z<merge_ports.<locals>.parse_sequence_func.<locals>.<listcomp>rQ  rY  )r[  Zaccrh   rh   ri   r\  U  s    z(merge_ports.<locals>.parse_sequence_funcrJ   c                 S   s   g | ]}|qS rh   rh   rV  rh   rh   ri   r   `  r   zmerge_ports.<locals>.<listcomp>targetr   )rO  r   ru   r  r   r   r]  r   )rp  r   r   r\  r*  r^  rh   rh   ri   ri  T  s    
ri  c                 C   s   dd }t ||||}|d |d |d |d |d |d |d	t |jd
tg d |dt |dt t|S )Nc                 S   s"   |  di }t|trd|iS |S )NrV   r+  )ru   rv   r   )r   Zbuild_configrh   rh   ri   to_dictd  s    
zmerge_build.<locals>.to_dictr+  rX   r   rx  rN   rE   r  Z
cache_fromra  rF   rA   )	rM  r`  rU  r  rQ  rf  r   r    rw   )outputr   r   ry  rp  rh   rh   ri   ro  c  s    





ro  c                 C   s  t | pi |pi }|d |d |d |dt |d |d |d |drt |jdpti |jdpi }|d	 |jd
t	i d t
||d< |drt |jdpi |jdpi }|d |jdtg d |jdtg d t
||d< t
|S )NmodeZendpoint_modeZreplicasrF   Zupdate_configZrollback_configZrestart_policyZ	resourcesZlimitsZreservationsra  Z	placementZmax_replicas_per_nodeconstraintsZpreferences)rM  r`  rU  r   rO  r   ru   r   rQ  merge_reservationsrw   rf  merge_unique_objects_lists)r   r   rp  Zresources_mdZplacement_mdrh   rh   ri   rl  x  s(    






"
"
rl  c                 C   s   i }t | t |B }t| tr,dd | D n| } t|trHdd |D n|}|D ]h}t| |pbi ||pni }|dtg  |dtg  |d |d |d t|||< qP|S )	Nc                 S   s   i | ]
}|i qS rh   rh   r   rh   rh   ri   r     r   z"merge_networks.<locals>.<dictcomp>c                 S   s   i | ]
}|i qS rh   rh   r   rh   rh   ri   r     r   aliasesZlink_local_ipspriorityZipv4_addressZipv6_address)	r   rv   r?  rM  ru   rQ  rf  r`  rw   )r   r   Zmerged_networksZall_network_namesZnetwork_namerp  rh   rh   ri   rd    s    


rd  c                 C   sF   t | |}|d |d |dtjj |jdtg d t|S )Nr9   ZmemoryZgeneric_resourcesr<   ra  )	rM  r`  r_  r   ZGenericResourcer/  rQ  r~  rw   r   r   rp  rh   rh   ri   r}    s    


r}  c                 C   s:   dd | | D }dd t dd | D tddD S )	Nc                 S   s   i | ]}t ||qS rh   r   r   irh   rh   ri   r     r   z.merge_unique_objects_lists.<locals>.<dictcomp>c                 S   s   g | ]}|d  qS )r   rh   r  rh   rh   ri   r     r   z.merge_unique_objects_lists.<locals>.<listcomp>c                 s   s   | ]\}}||fV  qd S ra   rh   r  rh   rh   ri   r     r   z-merge_unique_objects_lists.<locals>.<genexpr>r   r   )r   r   r   rv  rh   rh   ri   r~    s    r~  c                 C   s>   t | |}|d dd }dD ]}|j||g d q t|S )NZweightc                    sB   t d  fdd| D }| fdd|D  t|  dS )Nr   c                    s   i | ]} ||qS rh   rh   rs  Zget_pathrh   ri   r     r   zBmerge_blkio_config.<locals>.merge_blkio_limits.<locals>.<dictcomp>c                 3   s   | ]} ||fV  qd S ra   rh   rr  r  rh   ri   r     r   zAmerge_blkio_config.<locals>.merge_blkio_limits.<locals>.<genexpr>r   )r   r  r   r]  )r   r   indexrh   r  ri   merge_blkio_limits  s    z.merge_blkio_config.<locals>.merge_blkio_limits)r3  r6  r4  r7  Zweight_devicera  )rM  r`  rQ  rw   )r   r   rp  r  r*  rh   rh   ri   rj    s    

rj  c                 C   sj   t | |}|d |d| dks6| dd u rH|ddd  n|drb|di |d< t|S )Nr   rL  c                 S   s   | pi S ra   rh   rR  rh   rh   ri   <lambda>  r   zmerge_logging.<locals>.<lambda>)rM  r`  ru   rU  rw   r  rh   rh   ri   rh    s    

"
rh  c                 C   sr   |  dd  |  dd  d|v r.|d | d< n@d|v rD|d | d< n*d|v rZ|d | d< nd|v rn|d | d< d S )NrD   rV   )rH  )rz  r   r   rh   rh   ri   rn    s    rn  c                 C   s   t | }|t | |S ra   )r  r  )r   r   r  rh   rh   ri   merge_environment  s    r  c                 C   s   t | }|t | |S ra   )r   r  )r   r   rF   rh   rh   ri   merge_labels  s    r  c                 C   s    d| v r|  ddS | dfS d S )N=r    )split)Zkvpairrh   rh   ri   split_kv  s    r  c                    sN   |si S t |tr(t fdd|D S t |tr:t|S td||f d S )Nc                 3   s   | ]} |V  qd S ra   rh   )r   e
split_funcrh   ri   r     r   z%parse_dict_or_list.<locals>.<genexpr>z"%s "%s" must be a list or mapping,)rv   r?  rw   r   )r  	type_nameZ	argumentsrh   r  ri   parse_dict_or_list  s    

r  zbuild argumentsr@   rF   c                 C   s   | d fS ra   rh   r   rh   rh   ri   r    r   r  r|   rO   c                 C   s   | ddifS )Nr0  r1  rh   r  rh   rh   ri   r    r   r  c                 C   s&   | si S t | trt| S tdd S )NzInvalid type: expected mapping)rv   rw   r   drh   rh   ri   rb    s
    
rb  c                 C   s4   |d ur| |fS |r(| |v r(| ||  fS | d fS d S ra   rh   )r   valr@   rh   rh   ri   r    s
    r  c                    s    fdd|d D S )Nc                    s   g | ]}t  |qS rh   )resolve_volume_path)r   r   r  rh   ri   r     s   z(resolve_volume_paths.<locals>.<listcomp>rR   rh   )rT   r   rh   r  ri   r#    s    
r#  c                 C   s   t |tr>|dddr:|d dkr:t| |d |d< |S d }t|\}}|d ur|\}}|d u rj|S |dr~t| |}tj|}d	|||rd| ndS |S )	Nsourcer  ).~typer   r  z{}:{}{}:)
rv   rw   ru   r   r   split_path_mappingr   r   r   r   )rT   r   Zmount_paramscontainer_pathZ	host_pathr{  rh   rh   ri   r     s    


r  c                 C   sd   d| v r`i }t | d tr*| d|d< n.|| d  d|v rXtt|d||d< || d< d S )NrV   r+  r  )rv   r   rH  r  r   r  ru   )r   rT   r@   rV   rh   rh   ri   rJ  5  s    rJ  c                 C   s   t |r|S t| |S ra   )is_urlr   )rT   
build_pathrh   rh   ri   r,  F  s    r,  c                 C   s
   |  tS ra   )r   DOCKER_VALID_URL_PREFIXES)r  rh   rh   ri   r  L  s    r  c                 C   sv   d| v rr|  di }t|tr$|}n t|tr@d|v r@|d }nd S t|srtj|rft|tj	srt
d| d S )NrV   r+  zNbuild path %s either does not exist, is not accessible, or is not a valid URL.)ru   rv   r   rw   r  r   r   r   accessR_OKr   )r   rV   r  rh   rh   ri   r  P  s$    


r  c                 C   s   t | }|t | t|S ra   )dict_from_path_mappingsr  path_mappings_from_dict)r   r   r  rh   rh   ri   re  e  s    re  c                 C   s   | rt dd | D S i S d S )Nc                 s   s   | ]}t |V  qd S ra   )r  r=  rh   rh   ri   r   m  r   z*dict_from_path_mappings.<locals>.<genexpr>)rw   )Zpath_mappingsrh   rh   ri   r  k  s    r  c                 C   s   dd t |  D S )Nc                 S   s   g | ]}t |qS rh   )join_path_mappingr=  rh   rh   ri   r   s  r   z+path_mappings_from_dict.<locals>.<listcomp>)r   r   r  rh   rh   ri   r  r  s    r  c                 C   s   t | tr| d| fS t| \}}d|v rx|dd\}}t|\}}d}d|v rd|dd\}}|| || |ffS | dfS dS )z
    Ascertain if the volume_path contains a host path as well as a container
    path. Using splitdrive so windows absolute paths won't cause issues with
    splitting on ':'.
    rx  r  r   N)rv   rw   ru   r   r  rsplit)Zvolume_pathdriveZvolume_confighost	containerZcontainer_driver  r{  rh   rh   ri   r  v  s    
r  c                 C   s:   |  dg }g }|D ]}|t| q|r6|| d< | S )NrM   )ru   r-  r"   r/  )r   Zsecurity_optsrw  valuerh   rh   ri   r&    s    r&  c                 C   sP   | \}}t |tr|S |d u r"|S |\}}d||f}|rH|d| 7 }|S d S )Nr  )rv   rw   r   )Zpairr  r  r{  rw  rh   rh   ri   r    s    
r  c                 C   s   t jt j| t j|S ra   )r   r   r   r   r   )rT   r   rh   rh   ri   r     s    r   c                 C   s   t | t | S ra   )r!  r   rh   rh   ri   rg    s    rg  c                 C   s$   | d u rg S t | tr| gS | S d S ra   )rv   r   )r  rh   rh   ri   r!    s
    
r!  c                    s    fdd| D S )Nc                    s   i | ]}t | |qS rh   )r   rV  	key_fieldrh   ri   r     r   zto_mapping.<locals>.<dictcomp>rh   )Zsequencer  rh   r  ri   rZ    s    rZ  c                 C   s   t dd | D S )Nc                 s   s   | ]}|t jv V  qd S ra   )stringZascii_uppercase)r   charrh   rh   ri   r     r   z has_uppercase.<locals>.<genexpr>)anyr  rh   rh   ri   r    s    r  c              
   C   s   zFt | |rdnd|d}t|W  d    W S 1 s:0    Y  W nv ttjtfy } zV|d u rt| dddW  Y d }~S t|ddd	 |jj	 }t
d
||W Y d }~n
d }~0 0 d S )Nrbr)encodingz	utf-8-sigF)r  binaryrk   r  r  z{}: {})openr   r   OSErrorZ	YAMLErrorUnicodeDecodeErrorrp   r   rg   rj   r   r   )rq   r  r  Zfhr  Z
error_namerh   rh   ri   rp     s    .rp   )N)T)N)T)NT)NT)T)NT)r   r\   r   r   r  r   collectionsr   	itertoolsr   operatorr   r   r   r   r  r   constr
   r~   r   rx   Zutilsr   r   r   r   r   rs   r   r@   r   r   r   errorsr   r   r   r   r   Zinterpolationr   Zsort_servicesr   r   r   r   r    r!   r"   r#   r$   r%   r&   Z
validationr'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   ZDOCKER_CONFIG_KEYSrm  r  r   r   Z	getLoggerrj   r   r`   ro   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r   r   r"  r(  r%  r'  r)  rD  r   rK  r   rw   rM  r  rf  rk  ri  ro  rl  rd  r}  r~  rj  rh  rn  r  r  r  r  partialr  r  r   rI  r$  rc  rb  r  r#  r  rJ  r,  r  r  re  r  r  r  r&  r  r   rg  r!  rZ  r  rp   rh   rh   rh   ri   <module>   s  ?	
V
	
*
!
1	
6Z
$# 
.--	


	
	