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mZ d dlm	Z	 d dl
mZ d dl
mZ d dlZzd dl mZ W n eyK   d dlmZ Y nw 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&l7m8Z8 dd'l7m9Z9 dd(l7m:Z: dd)l7m;Z; dd*l7m<Z< dd+l7m=Z= dd,l7m>Z> dd-l7m?Z? dd.l7m@Z@ dd/l7mAZA dd0l7mBZB dd1l7mCZC dd2l7mDZD dd3l7mEZE dd4l7mFZF g d5¢ZGeGg d6¢ ZHd7ZIg d8¢ZJd9ZKe LeM¡ZNG d:d;„ d;ed<d=ƒƒZOG d>d?„ d?ed@dAƒƒZPG dBdC„ dCedDdEƒƒZQG dFdG„ dGedHdIƒƒZRdØdJdK„ZSdLdM„ ZTdNdO„ ZUdPdQ„ ZVdRdS„ ZWdTdU„ ZXdÙdWdX„ZYdØdYdZ„ZZd[d\„ Z[d]d^„ Z\dÙd_d`„Z]dadb„ Z^dcdd„ Z_dÚdedf„Z`G dgdh„ dhƒZadÚdidj„Zbdkdl„ Zcdmdn„ Zddodp„ Zedqdr„ Zfdsdt„ Zgdudv„ Zhdwdx„ Zidydz„ Zjd{d|„ Zkd}d~„ Zl	VdÙdd€„Zmdd‚„ Zndƒd„„ ZoG d…d†„ d†epƒZqd‡dˆ„ Zrd‰dŠ„ Zsd‹dŒ„ ZtddŽ„ Zudd„ Zvd‘d’„ Zwd“d”„ Zxd•d–„ Zyd—d˜„ Zzd™dš„ Z{d›dœ„ Z|ddž„ Z}dŸd „ Z~d¡d¢„ Zd£d¤„ Z€d¥d¦„ Ze  ‚ee"d§¡Zƒe  ‚ee"d¨¡Z„e  ‚ee€d©¡Z…e  ‚edªd«„ d¬¡Z†e  ‚ee€d­¡Z‡e  ‚ed®d«„ d¯¡Zˆd°d±„ Z‰d²d³„ ZŠd´dµ„ Z‹d¶d·„ ZŒd¸d¹„ Zdºd»„ ZŽd¼d½„ Zd¾d¿„ ZdÀdÁ„ Z‘dÂdÃ„ Z’dÄdÅ„ Z“dÆdÇ„ Z”dÈdÉ„ Z•dÊdË„ Z–dÌdÍ„ Z—dÎdÏ„ Z˜dÐdÑ„ Z™dÒdÓ„ ZšdÔdÕ„ Z›dÚdÖd×„Zœd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_dropÚcgroup_parentÚcommandÚ	cpu_countÚcpu_percentÚ
cpu_periodÚ	cpu_quotaÚcpu_rt_periodÚcpu_rt_runtimeÚ
cpu_sharesÚcpusÚcpusetÚdetachÚdevice_cgroup_rulesÚdevicesÚdnsÚ
dns_searchÚdns_optÚ
domainnameÚ
entrypointÚenv_fileÚenvironmentÚextra_hostsÚ	group_addÚhostnameÚhealthcheckÚimageÚipcÚ	isolationÚlabelsÚlinksÚmac_addressÚ	mem_limitÚmem_reservationÚmemswap_limitÚmem_swappinessÚnetÚoom_score_adjÚoom_kill_disableÚpidÚportsÚ
privilegedÚ	read_onlyÚrestartÚruntimeÚsecretsÚsecurity_optÚshm_sizeÚ
pids_limitÚ
stdin_openÚstop_signalÚsysctlsÚttyÚuserÚuserns_modeÚvolume_driverÚvolumesÚvolumes_fromÚworking_dir)Úblkio_configÚbuildÚcontainer_nameÚcredential_specÚ
dockerfileÚinitÚ
log_driverÚlog_optÚloggingÚnetwork_modeÚplatformÚprofilesÚscaleÚstop_grace_period)zhttp://zhttps://zgit://zgithub.com/zgit@)zdocker-compose.ymlzdocker-compose.yamlzcompose.ymlzcompose.yaml)zdocker-compose.override.ymlzdocker-compose.override.yamlzcompose.override.ymlz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   Úfrom_env_fileÚsuperÚ__new__)Úclsrq   Úconfig_filesrL   ©Ú	__class__© ú7/usr/lib/python3/dist-packages/compose/config/config.pyr„   ²   s
   
ÿzConfigDetails.__new__r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r„   Ú__classcell__r‰   r‰   r‡   rŠ   r€   ©   s    r€   Ú_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 r   )Ú	load_yaml)r…   Úfilenamer‰   r‰   rŠ   Ú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   r•   )Úselfr•   r‰   r‰   rŠ   Úconfig_versionÆ   s   
zConfigFile.config_versionc                 C   s  | j  dd ¡}|sA| j  dd ¡}| j  dd ¡}| j  dd ¡}|s$|s$|r7dD ]}t| j| j  |i ¡|ƒ q&tS t| j| j dƒ tS t|tƒrRt 	d 
| jt¡¡ tS t|tƒs_td 
| j¡ƒ‚t|tƒrwt d¡}| |¡swtd	 
|| j¡ƒ‚| d
¡r…td 
| jt¡ƒ‚tS )Nr•   ÚservicesÚnetworksro   )r   rž   ro   z‚Unexpected 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. {})r–   r—   r)   r“   ÚVERSIONrš   r˜   r™   ÚlogÚwarningÚformatÚstrr   ÚreÚcompileÚmatchÚ
startswithr   )r›   r•   r   rž   ro   ÚsectionÚversion_patternr‰   r‰   rŠ   r•   Í   sL   ÿ
ÿ

þ
þ



þ

þzConfigFile.versionc                 C   s   |   ¡ | S r   ©Úget_service_dicts)r›   Únamer‰   r‰   rŠ   Úget_serviceû   s   zConfigFile.get_servicec                 C   s   | j tkr| jS | j di ¡S )Nr   ©r•   rš   r–   r—   ©r›   r‰   r‰   rŠ   r¬   þ   s   
zConfigFile.get_service_dictsc                 C   ó   | j tkri S | j di ¡S )Nro   r¯   r°   r‰   r‰   rŠ   Úget_volumes  ó   zConfigFile.get_volumesc                 C   r±   )Nrž   r¯   r°   r‰   r‰   rŠ   Úget_networks  r³   zConfigFile.get_networksc                 C   r±   )Nrd   r¯   r°   r‰   r‰   rŠ   Úget_secrets	  r³   zConfigFile.get_secretsc                 C   r±   )NÚconfigsr¯   r°   r‰   r‰   rŠ   Úget_configs  r³   zConfigFile.get_configsN)r‹   rŒ   r   rŽ   Úclassmethodr”   r   rœ   r•   r®   r¬   r²   r´   rµ   r·   r‰   r‰   r‰   rŠ   r‘   º   s    


-r‘   Ú_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)r‹   rŒ   r   rŽ   r‰   r‰   r‰   rŠ   rº     s    rº   Ú_Configz@config_version version services volumes networks secrets configsc                   @   s   e Zd Zedd„ ƒZdS )ÚServiceConfigc                 C   s8   |st dƒ‚| tj |¡|rtj |¡||ƒS |||ƒS )Nz!No working_dir for ServiceConfig.)Ú
ValueErrorÚosÚpathÚabspath)r…   rq   r“   r­   r–   r‰   r‰   rŠ   Úwith_abs_paths%  s   
üüzServiceConfig.with_abs_pathsN)r‹   rŒ   r   r¸   rÁ   r‰   r‰   r‰   rŠ   r¼   #  s    r¼   Ú_ServiceConfigz working_dir filename name configc                    sÂ   |dgkrt |rtj |¡nt ¡ td t tj	¡ƒg|ƒS |r)‡ fdd„|D ƒ}nt
ˆ ƒ}|s5|s5ttƒ‚|sAt
|ƒ}|sAttƒ‚t d d |¡¡¡ t |rQ|ntj |d ¡dd„ |D ƒ|ƒS )Nú-c                    s   g | ]	}t j ˆ |¡‘qS r‰   )r¾   r¿   Újoin©Ú.0Úf©Úbase_dirr‰   rŠ   Ú
<listcomp>:  ó    zfind.<locals>.<listcomp>zUsing configuration files: {}ú,r   c                 S   s   g | ]}t  |¡‘qS r‰   )r‘   r”   rÅ   r‰   r‰   rŠ   rÊ   J  ó    )r€   r¾   r¿   rÀ   Úgetcwdr‘   ÚyamlÚ	safe_loadÚsysÚstdinÚget_default_config_filesr   ÚSUPPORTED_FILENAMESr¡   Údebugr£   rÄ   Údirname)rÉ   Ú	filenamesrL   Úoverride_dirr‰   rÈ   rŠ   Úfind1  s*   
ýýrÙ   c                 C   sV   | d }t |ƒ | dd … D ]}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   r•   r   r£   r“   )r†   Ú	main_fileÚ	next_filer‰   r‰   rŠ   Úvalidate_config_versionO  s    üþÿýrÜ   c                 C   s`   t t| ƒ\}}|sd S |d }t|ƒdkr$t 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_dirsrÔ   Úlenr¡   r¢   rÄ   r¾   r¿   Úget_default_override_file)rÉ   Ú
candidatesr¿   Úwinnerr‰   r‰   rŠ   rÓ   `  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 r‰   ©r¾   r¿   ÚexistsrÄ   )rÆ   Úoverride_filename©r¿   r‰   rŠ   rÊ   p  s    þz-get_default_override_file.<locals>.<listcomp>r   )ÚDEFAULT_OVERRIDE_FILENAMESrß   r   )r¿   Úoverride_files_in_pathr‰   ræ   rŠ   rà   o  s   
ÿrà   c                    sN   ‡ fdd„| D ƒ}|s#t j ˆ d¡}t j |¡t j ˆ ¡kr#t| |ƒ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 r‰   rã   )rÆ   r“   ræ   r‰   rŠ   rÊ   €  s    
ÿz2find_candidates_in_parent_dirs.<locals>.<listcomp>z..)r¾   r¿   rÄ   rÀ   rÞ   )r×   r¿   rá   Ú
parent_dirr‰   ræ   rŠ   rÞ   x  s   
rÞ   c                    sN   d}d‰ ‡ fdd„| D ƒ}|r%t  |jd tdd„ |D ƒƒ¡ˆ d¡ d S d S )	Nz§Some 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 r‰   )r—   ©rÆ   Ús©Úkeyr‰   rŠ   rÊ   ’  rË   z+check_swarm_only_config.<locals>.<listcomp>rÝ   c                 s   s    | ]}|d  V  qdS )r­   Nr‰   rê   r‰   r‰   rŠ   Ú	<genexpr>–  ó   € z*check_swarm_only_config.<locals>.<genexpr>)r   rí   )r¡   r¢   r£   rÄ   Úsorted)Úservice_dictsÚwarning_templater   r‰   rì   rŠ   Úcheck_swarm_only_config‹  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rQ|D ]}	t|	|ƒ qIt	|ƒ 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_filerL   )rÆ   Úconfig_file©Úconfig_detailsrõ   r‰   rŠ   rÊ   §  s    ÿÿzload.<locals>.<listcomp>)r†   r   r²   ÚVolumer´   ÚNetworkrµ   ÚSecretr·   rº   rô   )rÜ   r†   Ú_replaceÚload_mappingrq   Úload_servicesr•   rš   r'   ró   rº   rœ   )
rù   rõ   Úprocessed_filesrÚ   ro   rž   rd   r¶   rñ   Úservice_dictr‰   rø   rŠ   Úloadœ  s4   
	þ
ÿÿÿÿ


ÿr  c           
      C   sì   i }| D ]o}t ||ƒƒ  ¡ D ]d\}}|pi ||< |sq| d¡}|r@t||||jƒ t|tƒr7| d¡|d< n	| d¡s@||d< d|v rLt|d ƒ|d< d|v rYt||d ƒ|d< d|v rrt	|d ƒ|d< t
||ƒ}	|	rr|	|d d< qq|S )NÚexternalr­   rT   ÚfileÚdriver_optsÚdevice)ÚgetattrÚitemsr—   Úvalidate_externalr•   r˜   r™   Úparse_labelsÚexpand_pathr   Úformat_device_option)
r†   Úget_funcÚentity_typerq   Úmappingr÷   r­   r–   r  r  r‰   r‰   rŠ   rþ   Æ  s6   


ÿ
€çrþ   c                 C   st   | dkrd S |  dd¡}|dkrd S |d   d¡}|d   d¡}|r4|dkr6|r8tj tj |¡¡}|S d S d S d S )Nrú   ÚdriverÚlocalr  Úor  Úbind)r—   r¾   r¿   rÀ   Ú
expanduser)r  r–   r  r  r  Úfullpathr‰   r‰   rŠ   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  Nr‰   ©rÆ   Úkr‰   r‰   rŠ   rî   ý  ó   € z$validate_external.<locals>.<genexpr>)Úkeysr   r£   rÄ   )r  r­   r–   r•   r  r‰   r‰   rŠ   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©rL   ©r–   )r¼   rÁ   rq   r“   ÚServiceExtendsResolverrL   Úprocess_serviceÚrunrý   Úvalidate_serviceÚfinalize_servicer•   )Úservice_namer  Úservice_namesÚservice_configÚresolver)rù   r÷   rõ   r‰   rŠ   Úbuild_service  s(   üÿûz$load_services.<locals>.build_servicec                    s$   |   ¡ ‰ t‡‡ fdd„|  ¡ D ƒƒS )Nc                    s   g | ]
\}}ˆ ||ˆƒ‘qS r‰   r‰   )rÆ   r­   r  )r%  r"  r‰   rŠ   rÊ     s    
ÿÿz9load_services.<locals>.build_services.<locals>.<listcomp>)r  r   r  )r#  )r%  )r"  rŠ   Ú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 r‰   )Úmerge_service_dicts_from_filesr—   r•   )rÆ   r­   )Úbaser÷   Úoverrider‰   rŠ   Ú
<dictcomp>   s    ü

ýÿz9load_services.<locals>.merge_services.<locals>.<dictcomp>)Úset)r(  r)  Úall_service_names)r÷   ©r(  r)  rŠ   Úmerge_services  s   ûz%load_services.<locals>.merge_servicesc                 S   ó   g | ]}|  ¡ ‘qS r‰   r«   )rÆ   r  r‰   r‰   rŠ   rÊ   (  s    ÿz!load_services.<locals>.<listcomp>)r†   Ú	functoolsÚreduce)rù   r÷   rõ   r&  r.  Úservice_configsr#  r‰   )r%  rù   r÷   rõ   rŠ   rÿ      s   
ÿrÿ   c                 C   s   t | j|||ƒS r   )r   r•   )r÷   r–   r©   rL   r‰   r‰   rŠ   Úinterpolate_config_section1  s   ür3  c                 C   s&   t | j||ƒ |rt| j|||ƒS |S r   )r)   r“   r   r•   )r÷   r–   r©   rL   rõ   r‰   r‰   rŠ   Úprocess_config_section:  s   ür4  c                 C   sÐ   t | |  ¡ d||ƒ}| jtkrIt| jƒ}||d< t | |  ¡ d||ƒ|d< t | |  ¡ d||ƒ|d< t | |  ¡ d||ƒ|d< t | |  	¡ d	||ƒ|d
< n|}| j
|d} t| | jƒ |rf||vrftd || j¡ƒ‚| S )NÚservicer   Úvolumero   Únetworkrž   Úsecretrd   r–   r¶   r  ú3Cannot extend service '{}' in {}: Service not found)r4  r¬   r•   rš   r™   r–   r²   r´   rµ   r·   rý   r(   r   r£   r“   )r÷   rL   r!  rõ   r   Úprocessed_configr‰   r‰   rŠ   rö   F  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 r   )r#  rq   Úalready_seenr÷   rL   )r›   r#  r÷   rL   r;  r‰   r‰   rŠ   Ú__init__}  s
   

zServiceExtendsResolver.__init__c                 C   s   | j j| j jfS r   )r#  r“   r­   r°   r‰   r‰   rŠ   Ú	signature„  s   z ServiceExtendsResolver.signaturec                 C   s"   | j | jv rt| j| j g ƒ‚d S r   )r=  r;  r   r°   r‰   r‰   rŠ   Údetect_cycleˆ  s   ÿz#ServiceExtendsResolver.detect_cyclec                 C   s6   |   ¡  d| jjv r| j|  ¡ Ž }| jj|dS | jS )NÚextendsr  )r>  r#  r–   Úresolve_extendsÚvalidate_and_construct_extendsrý   )r›   r  r‰   r‰   rŠ   r  Œ  s
   zServiceExtendsResolver.runc                 C   s°   | j jd }t|tƒsd|i}|  |¡}|d }|tj | jj	¡kr:z| j 
|¡}W n( ty9   td ||¡ƒ‚w t |¡}t| j|gƒ t|| j|d}| 
|¡}|||fS )Nr?  r5  r9  )r!  )r#  r–   r˜   r™   Úget_extended_config_pathr¾   r¿   rÀ   r÷   r“   r®   ÚKeyErrorr   r£   r‘   r”   rÜ   rö   rL   )r›   r?  Úconfig_pathr!  r#  Úextends_fileÚextended_filer‰   r‰   rŠ   rA  •  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;  rL   )r  r¼   rÁ   r¾   r¿   rÖ   r÷   r;  r=  rL   r  r  Úvalidate_extended_service_dictÚmerge_service_dictsr#  r–   r•   )r›   Úextended_config_pathr  r!  r$  r#  Úother_service_dictr‰   r‰   rŠ   r@  ¯  s.   
üøýýz&ServiceExtendsResolver.resolve_extendsc                 C   s4   | j j}t| j j||ƒ d|v rt| j|d ƒS |S )z¸Service 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#  r“   r-   r­   r  rq   )r›   Úextends_optionsr“   r‰   r‰   rŠ   rB  Ç  s   ýz/ServiceExtendsResolver.get_extended_config_pathr   )r‹   rŒ   r   r<  Úpropertyr=  r>  r  rA  r@  rB  r‰   r‰   r‰   rŠ   r  |  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.
    rK   rL   c                 3   ó     | ]\}}t ||ˆ ƒV  qd S r   ©Úresolve_env_var©rÆ   r  Úvr  r‰   rŠ   rî   ß  ó   € z&resolve_environment.<locals>.<genexpr>)r—   Úupdater   Úparse_environmentr™   r  )r  rL   rõ   ÚenvrK   r‰   r  rŠ   Úresolve_environmentÖ  s
   rV  c                    s"   t | ƒ}t‡ fdd„| ¡ D ƒƒS )Nc                 3   rM  r   rN  rP  r  r‰   rŠ   rî   ä  rR  z%resolve_build_args.<locals>.<genexpr>)Úparse_build_argumentsr™   r  )Ú	buildargsrL   Úargsr‰   r  rŠ   Úresolve_build_argsâ  s   rZ  c                 C   sŒ   d  ||¡}d| v rtd| ƒ‚d| v rtd| ƒ‚d| v r*t| d ƒr*td| ƒ‚d| v r:t| d ƒr:td	| ƒ‚d
| v rDtd| ƒ‚d S )Nz!Cannot extend service '{}' in {}:rU   z+%s services with 'links' cannot be extendedrp   z2%s services with 'volumes_from' cannot be extendedr[   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  r“   r5  Úerror_prefixr‰   r‰   rŠ   rG  ç  s0   ÿÿÿÿÿÿrG  c                 C   s¬   dd„ }| j | j}}t|||ƒ |ƒ rt|ƒ t| ƒ t| ƒ t| |ƒ t| |ƒ t| |ƒ t	| |ƒ t
| |ƒ t| ƒ t| ƒ | d¡sRt|ƒrTtdj|dƒ‚d S d S )Nc                  S   s*   t jdd … } d| v rdS d| v rdS dS )Nr   ÚpullFz
--no-buildT)rÑ   Úargv)rY  r‰   r‰   rŠ   Úbuild_image  s   z%validate_service.<locals>.build_imagerQ   zÅService '{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­   )r–   r­   r3   Úvalidate_pathsr*   r5   r/   r1   r2   r,   r0   r.   r+   r—   Úhas_uppercaser   r£   )r#  r"  r÷   r_  r  r!  r‰   r‰   rŠ   r    s*   





ýÿÿr  c                    sâ   | j ‰ t| jƒ}d|v r‡ fdd„t|d ƒD ƒ|d< d|v r$t|ˆ ƒ d|v r6| d¡d u r6tˆ |ƒ|d< d|v rDtt|d ƒƒ|d< d|v rPt	|d ƒ|d< t
|ƒ}d	D ]}||v rdt|| ƒ||< qVtttt|ƒƒƒƒ}|S )
NrK   c                    ó   g | ]}t ˆ |ƒ‘qS r‰   )r  )rÆ   r¿   ©rq   r‰   rŠ   rÊ   *  ó    ÿÿz#process_service.<locals>.<listcomp>rs   ro   rn   rj   rT   )rF   rG   Útmpfs)rq   r™   r–   Úto_listÚprocess_build_sectionr—   Úresolve_volume_pathsr   Úparse_sysctlsr
  Úprocess_depends_onÚprocess_security_optÚprocess_blkio_configÚprocess_portsÚprocess_healthcheck)r#  r  Úfieldr‰   rd  rŠ   r  %  s.   



þ
€ÿr  c                 C   sŒ   t | d tƒrt|| d ƒ| d< d S t | d tƒrBd| d v r.| d d }t||ƒ| d d< d| d v rDt| d d ƒ| d d< d S d S d S )Nrs   ÚcontextrT   )r˜   r¤   Úresolve_build_pathr™   r
  )r  rq   r¿   r‰   r‰   rŠ   rh  H  s   ûrh  c                 C   sP   d| vr| S g }| d D ]}t |tƒr| |¡ q| t |¡¡ q|| d< | S )Nr_   )r˜   r$   ÚappendÚextendÚparse)r  r_   Úport_definitionr‰   r‰   rŠ   rn  S  s   
rn  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_startedr‰   )rÆ   Úsvcr‰   r‰   rŠ   r*  c  s    
ÿz&process_depends_on.<locals>.<dictcomp>)r˜   r™   ©r  r‰   r‰   rŠ   rk  a  s
   
ÿrk  c                 C   sÖ   |   d¡s| S dD ],}|| d v r5| d   |g ¡D ]}|  dd¡}t|ƒ|d< |d d u r4td |¡ƒ‚qq	dD ]0}|| d v rh| d   |g ¡D ]}zt|  dd¡ƒ|d< W qH tyg   td |  d¡¡ƒ‚w q8| S )Nrr   )Ú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.)r—   r   r   r£   Úintr½   )r  rp  rQ  r}  r‰   r‰   rŠ   rm  i  s.   
ÿ€ÿÿ€rm  c                 C   sb   d| vr| S | d }d|v r|d= dg|d< dD ]}||vs%t || tƒr&qt|| ƒ||< q| S )NrP   ÚdisableÚNONEÚtest)ÚintervalÚtimeoutÚstart_period)r˜   r€  r   )r  Úhcrp  r‰   r‰   rŠ   ro  ‚  s   
ro  c           	      C   sÌ   d| v rdg }|  d¡}|  d¡}| d D ]}t|tƒr&| t |||¡¡ q| t |||¡¡ qg }dd„ |D ƒ}|D ]}ttt	dƒ|ƒƒ 
|j¡dkrT| | ¡ ¡ q<|r`tdd	 |¡ ƒ‚|| d< | S )
Nro   ÚCOMPOSE_CONVERT_WINDOWS_PATHSÚCOMPOSE_FORCE_WINDOWS_HOSTc                 S   s"   g | ]}t |tƒr| ¡ n|‘qS r‰   )r˜   r   Úas_volume_spec©rÆ   rQ  r‰   r‰   rŠ   rÊ      s   " z,finalize_service_volumes.<locals>.<listcomp>Úinternalr   zDuplicate mount points: [%s]rÝ   )Úget_booleanr˜   r™   rs  r   ru  r&   ÚlistÚmapr   ÚcountrŒ  Úreprr   rÄ   )	r  rL   Úfinalized_volumesÚ	normalizeÚwin_hostrQ  Úduplicate_mountsÚmountsÚmountr‰   r‰   rŠ   Úfinalize_service_volumes”  s(   


€ÿr˜  c                    s.  t | jƒ}d|v sd|v rt|||ƒ|d< | dd ¡ d|v r-‡ ‡fdd„|d D ƒ|d< t||ƒ}d|v rQ| d¡}t|ƒ}|rM|ˆ v rMd |¡|d< n||d< d	|v r]t|d	 ƒ|d	< d
|v rit|d
 ƒ|d
< d|v rxdd„ |d D ƒ|d< d|v r‡dd„ |d D ƒ|d< t	|| j
|ƒ | j|d< t|ƒS )NrL   rK   rp   c                    s   g | ]	}t  |ˆ ˆ¡‘qS r‰   )r%   ru  )rÆ   Úvf©r"  r•   r‰   rŠ   rÊ   ·  s    ÿÿz$finalize_service.<locals>.<listcomp>r[   z
service:{}r{   rž   rb   rd   c                 S   ó   g | ]}t j |¡‘qS r‰   )r   ÚServiceSecretru  rê   r‰   r‰   rŠ   rÊ   Í  ó    ÿr¶   c                 S   r›  r‰   )r   r¼   ru  )rÆ   Úcr‰   r‰   rŠ   rÊ   Ò  r  r­   )r™   r–   rV  Úpopr˜  r   r£   Úparse_networksr!   Únormalize_buildrq   r­   Únormalize_v1_service_format)r#  r"  r•   rL   rõ   r  r{   rt   r‰   rš  rŠ   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 rF|   di ¡| d< | d  d|  d¡i¡ | S )Nrx   ry   rz   r  Úoptionsrv   rs   )r—   rS  rŸ  rz  r‰   r‰   rŠ   r¢  Ü  s   
ÿr¢  c                 C   s<   t | ||ƒ}d|v r|d |d< |S d| v r| d |d< |S )z³When 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?  )rH  )r(  r)  r•   Únew_servicer‰   r‰   rŠ   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 r   r-  )r›   r(  r)  r‰   r‰   rŠ   r<     s   
zMergeDict.__init__c                 C   s   || j v p	|| jv S r   r-  ©r›   rp  r‰   r‰   rŠ   Úneeds_merge  s   zMergeDict.needs_mergeNc                 C   s4   |   |¡sd S || j ||¡| j ||¡ƒ| |< d S r   )r§  r(  r—   r)  )r›   rp  Ú
merge_funcÚdefaultr‰   r‰   rŠ   Úmerge_field  s   
þzMergeDict.merge_fieldc                 C   sP   |   |¡sd S |d u rdd„ }|| j |¡ƒ| |< | |  || j |¡ƒ¡ d S )Nc                 S   ó   | pi S r   r‰   ©Úmr‰   r‰   rŠ   Ú
parse_func  s   z+MergeDict.merge_mapping.<locals>.parse_func)r§  r(  r—   rS  r)  )r›   rp  r®  r‰   r‰   rŠ   Ú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   ó    | ]}ˆ |ƒV  qd S r   r‰   ©rÆ   Úitem©r®  r‰   rŠ   rî     rï   zHMergeDict.merge_sequence.<locals>.parse_sequence_func.<locals>.<genexpr>rª  ©Ú
to_mapping)Úseqr³  r‰   rŠ   Úparse_sequence_func  s   z5MergeDict.merge_sequence.<locals>.parse_sequence_funcc                 S   r/  r‰   )r‘  r±  r‰   r‰   rŠ   rÊ   #  ó    z,MergeDict.merge_sequence.<locals>.<listcomp>)r§  r(  r—   rS  r)  rð   Úvalues)r›   rp  r®  r·  Úmergedr‰   r³  rŠ   Úmerge_sequence  s   
zMergeDict.merge_sequencec                 C   s,   |   |¡r| j || j |¡¡| |< d S d S r   )r§  r)  r—   r(  r¦  r‰   r‰   rŠ   Úmerge_scalar%  s   
ÿzMergeDict.merge_scalarr   )
r‹   rŒ   r   rŽ   r<  r§  rª  r¯  r»  r¼  r‰   r‰   r‰   rŠ   r¥  ý  s    

r¥  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¡ qXdD ]
}|j|tg d qcdD ]}| |t¡ qp|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 ]}| |¡ q§|tkr½t|| |ƒ t |ƒS | d¡rÊt|| |ƒ|d< t |ƒS )NrL   rT   Úulimitsrj   r[  Ústorage_optrU   rd   r¶   re   rM   rž   ©r©  )ro   rE   )r6   r7   ÚexposeÚexternal_linksrp   rD   r}   )rF   rG   rK   rf  rz   rr   rP   Údeployrs   )!r¥  r¯  rT  r
  Úparse_flat_dictrj  Úparse_depends_onr»  r#   ru  r   rœ  r¼   r"   r    rª  Ú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¼  rš   Úlegacy_v1_merge_image_or_buildr§  Úmerge_buildr™   )r(  r)  r•   Úmdrp  r‰   r‰   rŠ   rH  *  s@   

ýrH  c                 C   s.   dd„ |D ƒ}dd„ | D ƒ} t tt| |ƒƒƒS )Nc                 s   ó    | ]}t |ƒV  qd S r   ©r¤   ©rÆ   r  r‰   r‰   rŠ   rî   X  rï   z+merge_unique_items_lists.<locals>.<genexpr>c                 s   rÒ  r   rÓ  ©rÆ   Úbr‰   r‰   rŠ   rî   Y  rï   )rð   r+  r   r-  r‰   r‰   rŠ   rÇ  W  s   rÇ  c                 C   s(   |  d¡du r	|S |  ¡ }| |¡ |S )NÚdisabledT)r—   ÚcopyrS  ©r(  r)  Úresultr‰   r‰   rŠ   rÌ  ]  s
   
rÌ  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 r‰   )r$   ru  )rÆ   r²  rë   r‰   r‰   rŠ   rÊ   g  s     z<merge_ports.<locals>.parse_sequence_func.<locals>.<listcomp>rª  r´  )r¶  Úaccr‰   r‰   rŠ   r·  f  s   
z(merge_ports.<locals>.parse_sequence_funcr_   c                 S   s   g | ]}|‘qS r‰   r‰   r±  r‰   r‰   rŠ   rÊ   q  s    zmerge_ports.<locals>.<listcomp>Útargetrì   )r§  r(  r—   rS  r)  rð   r¹  r   )rÑ  r(  r)  r·  rp  rº  r‰   r‰   rŠ   rÊ  e  s   
&rÊ  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 )Nrs   rq  )r—   r˜   r¤   )r5  Úbuild_configr‰   r‰   rŠ   Úto_dictu  s   
zmerge_build.<locals>.to_dictrq  rv   r7  rÜ  rf   rS   rY  Ú
cache_fromr¿  rT   rM   )	r¥  r¼  r¯  rW  rª  rÇ  r
  r    r™   )Úoutputr(  r)  rÞ  rÑ  r‰   r‰   rŠ   rÐ  t  s   





rÐ  c                 C   s  t | pi |pi ƒ}| d¡ | d¡ | d¡ | dt¡ | d¡ | d¡ | d¡ | d¡rVt |j d¡p:i |j d¡pAi ƒ}| d	¡ |jd
t	i d t
|ƒ|d< | d¡r‡t |j d¡pci |j d¡pji ƒ}| d¡ |jdtg d |jdtg d t
|ƒ|d< t
|ƒS )NÚmodeÚendpoint_modeÚreplicasrT   Úupdate_configÚrollback_configÚrestart_policyÚ	resourcesÚlimitsÚreservationsr¿  Ú	placementÚmax_replicas_per_nodeÚconstraintsÚpreferences)r¥  r¼  r¯  r
  r§  r(  r—   r)  rª  Úmerge_reservationsr™   rÇ  Úmerge_unique_objects_lists)r(  r)  rÑ  Úresources_mdÚplacement_mdr‰   r‰   rŠ   rÍ  ‰  s(   






"

"
rÍ  c                 C   s¾   i }t | ƒt |ƒB }t| tƒrdd„ | D ƒn| } t|tƒr$dd„ |D ƒn|}|D ]4}t|  |¡p1i | |¡p7i ƒ}| dtg ¡ | dtg ¡ | d¡ | d¡ | d¡ t|ƒ||< q(|S )	Nc                 S   ó   i | ]}|i “qS r‰   r‰   r  r‰   r‰   rŠ   r*  ¤  ó    z"merge_networks.<locals>.<dictcomp>c                 S   rò  r‰   r‰   r  r‰   r‰   rŠ   r*  ¥  ró  ÚaliasesÚlink_local_ipsÚpriorityÚipv4_addressÚipv6_address)	r+  r˜   rŽ  r¥  r—   rª  rÇ  r¼  r™   )r(  r)  Úmerged_networksÚall_network_namesÚnetwork_namerÑ  r‰   r‰   rŠ   rÅ  ¡  s   


rÅ  c                 C   sF   t | |ƒ}| d¡ | d¡ | dtjj¡ |jdtg d t|ƒS )NrA   ÚmemoryÚgeneric_resourcesrE   r¿  )	r¥  r¼  r»  r   ÚGenericResourceru  rª  rï  r™   ©r(  r)  rÑ  r‰   r‰   rŠ   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 r‰   r   ©rÆ   Úir‰   r‰   rŠ   r*  »  rÍ   z.merge_unique_objects_lists.<locals>.<dictcomp>c                 S   s   g | ]}|d  ‘qS )r   r‰   r   r‰   r‰   rŠ   rÊ   ¼  r¸  z.merge_unique_objects_lists.<locals>.<listcomp>c                 s   s    | ]	\}}||fV  qd S r   r‰   rP  r‰   r‰   rŠ   rî   ¼  r  z-merge_unique_objects_lists.<locals>.<genexpr>r   rì   )rð   r  r   rÙ  r‰   r‰   rŠ   rï  º  s   (rï  c                 C   s>   t | |ƒ}| d¡ dd„ }dD ]
}|j||g d qt|ƒS )NÚweightc                    sB   t dƒ‰ ‡ fdd„| D ƒ}| ‡ fdd„|D ƒ¡ t| ¡ ˆ dS )Nr¿   c                    s   i | ]}ˆ |ƒ|“qS r‰   r‰   rÕ  ©Úget_pathr‰   rŠ   r*  Å  rÍ   zBmerge_blkio_config.<locals>.merge_blkio_limits.<locals>.<dictcomp>c                 3   s    | ]	}ˆ |ƒ|fV  qd S r   r‰   rÔ  r  r‰   rŠ   rî   Æ  r  zAmerge_blkio_config.<locals>.merge_blkio_limits.<locals>.<genexpr>rì   )r   rS  rð   r¹  )r(  r)  Úindexr‰   r  rŠ   Úmerge_blkio_limitsÃ  s   z.merge_blkio_config.<locals>.merge_blkio_limits)r{  r~  r|  r  Úweight_devicer¿  )r¥  r¼  rª  r™   )r(  r)  rÑ  r  rp  r‰   r‰   rŠ   rË  ¿  s   

rË  c                 C   sp   t | |ƒ}| d¡ | d¡|  d¡ks|  d¡d u r'| ddd„ ¡ t|ƒS | d¡r4| di ¡|d< t|ƒS )Nr  r£  c                 S   r«  r   r‰   r¬  r‰   r‰   rŠ   Ú<lambda>×  ó    zmerge_logging.<locals>.<lambda>)r¥  r¼  r—   r¯  r™   rÿ  r‰   r‰   rŠ   rÉ  Ó  s   

"
þrÉ  c                 C   s|   |   dd ¡ |   dd ¡ d|v r|d | d< d S d|v r$|d | d< d S d|v r0|d | d< d S d|v r<|d | d< d S d S )NrQ   rs   )rŸ  )rà  r(  r)  r‰   r‰   rŠ   rÏ  Ý  s   ÿrÏ  c                 C   ó   t | ƒ}| t |ƒ¡ |S r   )rT  rS  )r(  r)  rU  r‰   r‰   rŠ   Úmerge_environmentê  ó   r  c                 C   r
  r   )r
  rS  )r(  r)  rT   r‰   r‰   rŠ   Úmerge_labelsð  r  r  c                 C   s   d| v r
|   dd¡S | dfS )Nú=r   Ú )Úsplit)Úkvpairr‰   r‰   rŠ   Úsplit_kvö  s   r  c                    sJ   |si S t |tƒrt‡ fdd„|D ƒƒS t |tƒrt|ƒS td||f ƒ‚)Nc                 3   r°  r   r‰   )rÆ   Úe©Ú
split_funcr‰   rŠ   rî     rï   z%parse_dict_or_list.<locals>.<genexpr>z"%s "%s" must be a list or mapping,)r˜   rŽ  r™   r   )r  Ú	type_nameÚ	argumentsr‰   r  rŠ   Úparse_dict_or_listý  s   

ÿÿr  zbuild argumentsrL   rT   c                 C   s   | d fS r   r‰   ©r  r‰   r‰   rŠ   r    r	  r  rž   rj   c                 C   s   | ddifS )Nrw  rx  r‰   r  r‰   r‰   rŠ   r    s    r[  c                 C   s"   | si S t | tƒrt| ƒS tdƒ‚)NzInvalid type: expected mapping)r˜   r™   r   ©Údr‰   r‰   rŠ   rÃ    s
   
rÃ  c                 C   s0   |d ur| |fS |r| |v r| ||  fS | d fS r   r‰   )rí   ÚvalrL   r‰   r‰   rŠ   rO  !  s
   rO  c                    s   ‡ fdd„|d D ƒS )Nc                    rc  r‰   )Úresolve_volume_path)rÆ   r6  rd  r‰   rŠ   rÊ   +  re  z(resolve_volume_paths.<locals>.<listcomp>ro   r‰   )rq   r  r‰   rd  rŠ   ri  *  s   
þri  c                 C   sª   t |tƒr| dd¡ d¡r|d dkrt| |d ƒ|d< |S d }t|ƒ\}}|d urS|\}}|d u r5|S | d¡r?t| |ƒ}tj |¡}d 	|||rPd| ¡S d¡S |S )	NÚsourcer  )Ú.ú~Útyper  r  z{}:{}{}ú:)
r˜   r™   r—   r¨   r  Úsplit_path_mappingr¾   r¿   r  r£   )rq   r6  Úmount_paramsÚcontainer_pathÚ	host_pathrá  r‰   r‰   rŠ   r  1  s   


r  c                 C   sh   d| v r2i }t | d tƒr|  d¡|d< n| | d ¡ d|v r,tt| d¡|ƒƒ|d< || d< d S d S )Nrs   rq  rY  )r˜   r¤   rŸ  rS  r   rZ  r—   )r  rq   rL   rs   r‰   r‰   rŠ   r¡  F  s   ÿôr¡  c                 C   s   t |ƒr|S t| |ƒS r   )Úis_urlr  )rq   Ú
build_pathr‰   r‰   rŠ   rr  W  s   
rr  c                 C   s
   |   t¡S r   )r¨   ÚDOCKER_VALID_URL_PREFIXES)r(  r‰   r‰   rŠ   r'  ]  s   
r'  c                 C   s~   d| v r9|   di ¡}t|tƒr|}nt|tƒr d|v r |d }nd S t|ƒs;tj |¡r3t |tj	¡s=t
d| ƒ‚d S d S d S )Nrs   rq  zNbuild path %s either does not exist, is not accessible, or is not a valid URL.)r—   r˜   r¤   r™   r'  r¾   r¿   rä   ÚaccessÚR_OKr   )r  rs   r(  r‰   r‰   rŠ   ra  a  s(   

ÿ
þþÿÿñra  c                 C   s   t | ƒ}| t |ƒ¡ t|ƒS r   )Údict_from_path_mappingsrS  Úpath_mappings_from_dict)r(  r)  r  r‰   r‰   rŠ   rÆ  v  s   rÆ  c                 C   s   | rt dd„ | D ƒƒS i S )Nc                 s   rÒ  r   )r#  r‹  r‰   r‰   rŠ   rî   ~  rï   z*dict_from_path_mappings.<locals>.<genexpr>)r™   )Úpath_mappingsr‰   r‰   rŠ   r,  |  s   r,  c                 C   s   dd„ t |  ¡ ƒD ƒS )Nc                 S   s   g | ]}t |ƒ‘qS r‰   )Újoin_path_mappingr‹  r‰   r‰   rŠ   rÊ   „  r¸  z+path_mappings_from_dict.<locals>.<listcomp>)rð   r  r  r‰   r‰   rŠ   r-  ƒ  s   r-  c                 C   s€   t | tƒr|  d¡| fS t| ƒ\}}d|v r<| dd¡\}}t|ƒ\}}d}d|v r2| dd¡\}}|| || |ffS | df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 ':'.
    rÜ  r"  r   N)r˜   r™   r—   r   r  Úrsplit)Úvolume_pathÚdriveÚvolume_configÚhostÚ	containerÚcontainer_driver%  rá  r‰   r‰   rŠ   r#  ‡  s   
r#  c                 C   s:   |   dg ¡}g }|D ]
}| t |¡¡ q
|r|| d< | S )Nre   )r—   rs  r"   ru  )r  Úsecurity_optsrÚ  Úvaluer‰   r‰   rŠ   rl    s   rl  c                 C   sL   | \}}t |tƒr|S |d u r|S |\}}d ||f¡}|r$|d| 7 }|S )Nr"  )r˜   r™   rÄ   )Úpairr5  r4  rá  rÚ  r‰   r‰   rŠ   r/  §  s   
r/  c                 C   s   t j t j | t j |¡¡¡S r   )r¾   r¿   rÀ   rÄ   r  )rq   r¿   r‰   r‰   rŠ   r  µ  s   r  c                 C   s   t | ƒt |ƒ S r   )rg  r-  r‰   r‰   rŠ   rÈ  ¹  s   rÈ  c                 C   s    | d u rg S t | tƒr| gS | S r   )r˜   r¤   )r8  r‰   r‰   rŠ   rg  ½  s
   
rg  c                    s   ‡ fdd„| D ƒS )Nc                    s   i | ]}t |ˆ ƒ|“qS r‰   )r  r±  ©Ú	key_fieldr‰   rŠ   r*  Ç  s    zto_mapping.<locals>.<dictcomp>r‰   )Úsequencer;  r‰   r:  rŠ   rµ  Æ  ó   rµ  c                 C   s   t dd„ | D ƒƒS )Nc                 s   s    | ]}|t jv V  qd S r   )ÚstringÚascii_uppercase)rÆ   Úcharr‰   r‰   rŠ   rî   Ë  s   € z has_uppercase.<locals>.<genexpr>)Úanyr`  r‰   r‰   rŠ   rb  Ê  r=  rb  c              
   C   s´   z$t | |rdnd|d}t |¡W  d   ƒ W S 1 sw   Y  W d S  ttjtfyY } z%|d u rAt| dddW  Y d }~S t|ddƒd	 |jj	 }t
d
 ||¡ƒ‚d }~ww )NÚrbÚr)Úencodingz	utf-8-sigF)rD  ÚbinaryrŒ   r  r  z{}: {})ÚopenrÏ   rÐ   ÚOSErrorÚ	YAMLErrorÚUnicodeDecodeErrorr’   r  rˆ   r‹   r   r£   )r“   rD  rE  Úfhr  Ú
error_namer‰   r‰   rŠ   r’   Î  s   (ÿ€ùr’   r   )T)NT)r0  rz   r¾   r¥   r>  rÑ   Úcollectionsr   Ú	itertoolsr   Úoperatorr   r   rÏ   r   ÚImportErrorr  r   Úconstr
   r    r   rš   Úutilsr   r   r   r   r   r•   r   rL   r   r   r   Úerrorsr   r   r   r   r   Úinterpolationr   Úsort_servicesr   r   r   r   r    r!   r"   r#   r$   r%   r&   Ú
validationr'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   ÚDOCKER_CONFIG_KEYSrÎ  r)  rÔ   rç   Ú	getLoggerr‹   r¡   r€   r‘   rº   r¼   rÙ   rÜ   rÓ   rà   rÞ   ró   r  rþ   r  r	  rÿ   r3  r4  rö   r  rV  rZ  rG  r  r  rh  rn  rk  rm  ro  r˜  r   r¢  r'  r™   r¥  rH  rÇ  rÌ  rÊ  rÐ  rÍ  rÅ  rî  rï  rË  rÉ  rÏ  r  r  r  r  ÚpartialrW  rT  r
  r   rj  rÄ  rÃ  rO  ri  r  r¡  rr  r'  ra  rÆ  r,  r-  r#  rl  r/  r  rÈ  rg  rµ  rb  r’   r‰   r‰   r‰   rŠ   Ú<module>   s"   ÿ?
V
	

*!
1	
6
Z$#
ÿ.--	

ÿ
	
	