
    S`M                        d dl Z d dlZd dlZd dlZd dlZd dlmZ d dlmZ d dlm	Z	 d dlm
Z
 d dlmZ ddlmZ dd	lmZ d
dlmZ d
dlmZ d
dlmZ  ej*                  e      ZddddddddddddddZdZdZdZdj9                  e      Zdj9                  e      ZdZd jA                  d!j9                  ee"      jC                               Z" e	jF                  de#      d$        Z$ e	jF                  d%e#      d&        Z% e	jF                  d'e(      d)        Z&d* Z'd+ Z(d, Z)d- Z*d. Z+d/ Z,d0 Z-d1 Z.d2 Z/d3 Z0d4 Z1d5 Z2d6 Z3d7 Z4d8 Z5d9 Z6d: Z7d; Z8d< Z9d= Z:d> Z;d? Z<d@ Z=dA Z>dB Z?dC Z@dD ZAdE ZBdF ZCdG ZDdH ZEdI ZFy)J    N)
split_port)Draft4Validator)FormatChecker)RefResolver)ValidationError   )COMPOSEFILE_V1)NANOCPUS_SCALE   ConfigurationError)VERSION_EXPLANATION)"get_service_name_from_network_mode
cpu_sharesextra_hostsdeviceslinksmemswap_limitports
privilegedvolumesworking_dir)	cpu_shareadd_hosthosts
extra_hostdevicelinkmemory_swapport	privilege
priviliged	priviligevolumeworkdirz[a-zA-Z0-9\._\-]z^\d+(\-\d+)?(\/[a-zA-Z]+)?$z!(\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])z({IPV4_SEG}\.){{3}}{IPV4_SEG})IPV4_SEGz!^{IPV4_ADDR}/(\d|[1-2]\d|3[0-2])$)	IPV4_ADDRz[0-9a-fA-F]{1,4} a9  
^
(
    (({IPV6_SEG}:){{7}}{IPV6_SEG})|
    (({IPV6_SEG}:){{1,7}}:)|
    (({IPV6_SEG}:){{1,6}}(:{IPV6_SEG}){{1,1}})|
    (({IPV6_SEG}:){{1,5}}(:{IPV6_SEG}){{1,2}})|
    (({IPV6_SEG}:){{1,4}}(:{IPV6_SEG}){{1,3}})|
    (({IPV6_SEG}:){{1,3}}(:{IPV6_SEG}){{1,4}})|
    (({IPV6_SEG}:){{1,2}}(:{IPV6_SEG}){{1,5}})|
    (({IPV6_SEG}:){{1,1}}(:{IPV6_SEG}){{1,6}})|
    (:((:{IPV6_SEG}){{1,7}}|:))|
    (fe80:(:{IPV6_SEG}){{0,4}}%[0-9a-zA-Z]{{1,}})|
    (::(ffff(:0{{1,4}}){{0,1}}:){{0,1}}{IPV4_ADDR})|
    (({IPV6_SEG}:){{1,4}}:{IPV4_ADDR})
)
/(\d|[1-9]\d|1[0-1]\d|12[0-8])
$
)IPV6_SEGr'   )formatraisesc                 f    	 t        |        y# t        $ r}t        t        |            d }~ww xY w)NT)r   
ValueErrorr   str)instancees     ;/usr/lib/python3/dist-packages/compose/config/validation.pyformat_portsr2   E   s5    &8   &c!f%%&s    	0+0exposec                 n    t        | t              r%t        j                  t        |       st        d      y)Nz)should be of the format 'PORT[/PROTOCOL]'T)
isinstancer.   rematchVALID_EXPOSE_FORMATr   r/   s    r1   format_exposer:   N   s0    (C xx+X6!;= =     subnet_ip_address)r+   c                     t        | t              r?t        j                  t        |       s%t        j                  t
        |       st        d      y)Nzshould use the CIDR formatT)r5   r.   r6   r7   VALID_REGEX_IPV4_CIDRVALID_REGEX_IPV6_CIDRr   r9   s    r1   format_subnet_ip_addressr@   X   s9    (C xx-x8HH2H=!">??r;   c           	          | j                  dg       }|D ]U  }|j                  s|j                  |vst        dj	                  |j                         | j                  d                   y )Nr   z^Named volume "{}" is used in service "{}" but no declaration was found in the volumes section.name)getis_named_volumeexternalr   r*   repr)service_dictproject_volumesservice_volumesvolume_specs       r1   match_named_volumesrK   b   sp    "&&y"5O& &&;+?+?+V$AAG$$&(8(8(@B r;   c           	      b    t        |       j                  }dddddddddj                  ||      S )Nmappingarraynumberbooleanstring)dictlistintfloatboolunicoder.   bytes)type__name__rC   )type_	type_names     r1   python_type_to_yaml_typer]   n   sA    U$$I	 
c)Y	 r;   c                    t        |t              s/t        dj                  | |t	        t        |                        |j                         D ]}  \  }}t        |t              st        dj                  | ||            t        |t        t        d      f      rOt        dj                  | ||t	        t        |                         y)zValidate the structure of a configuration section. This must be done
    before interpolation so it's separate from schema validation.
    z>In file '{filename}', {section} must be a mapping, not {type}.)filenamesectionrY   zWIn file '{filename}', the {section} name {name} must be a quoted string, i.e. '{name}'.)r_   r`   rB   NzFIn file '{filename}', {section} '{name}' must be a mapping not {type}.)r_   r`   rB   rY   )	r5   rR   r   r*   anglicize_json_typer]   itemsr.   rY   )r_   configr`   keyvalues        r1   validate_config_sectionrf   |   s     fd# f!()A&)IJ  LM 	M lln P
U#s#$006%# 17 1  %$T
!34$ &%#,-Ee-LM	 ! OP PPr;   c                     t        | j                  t              s8t        dj	                  | j
                  t        | j                                    y )Nz8Top level object in '{}' needs to be an object not '{}'.)r5   rc   rR   r   r*   r_   rY   )config_files    r1   validate_top_level_objectri      sI    k(($/ FMM$$[''(*+ 	+ 0r;   c                     | j                   j                  di       }|j                         D ]=  \  }}t        |t              s|d   |d   k  r#t        dj                  | |             y )NulimitssofthardzdService '{s.name}' has invalid ulimit '{ulimit}'. 'soft' value can not be greater than 'hard' value )sulimit)rc   rC   rb   r5   rR   r   r*   )service_configulimit_config
limit_namesoft_hard_valuess       r1   validate_ulimitsrt      s    "))--i<M(5(;(;(= /$
$&-#F+/?/GG(IIO(, JP J./ //r;   c                 8    d| z  }d|vr|t        d|z        yy)zo
    The service to be extended must either be defined in the config key 'file',
    or within 'filename'.
    z'Invalid 'extends' configuration for %s:fileNz;%s you need to specify a 'file', e.g. 'file: something.yml'r   )service_nameextends_optionsr_   error_prefixs       r1   validate_extends_file_pathrz      s8    
 =|KL_$)9 ILX
 	
 *:$r;   c                     | j                   j                  d      }|sy d| j                   v rt        d      t        |      }|sy ||vrt        dj	                  | |            y )Nnetwork_modenetworksz0'network_mode' and 'networks' cannot be combinedzPService '{s.name}' uses the network stack of service '{dep}' which is undefined.rn   dep)rc   rC   r   r   r*   )rp   service_namesr|   
dependencys       r1   validate_network_moder      sw    !((,,^<L^*** !STT3LAJ& "F^FDF 	F 'r;   c                     | j                   j                  d      }|sy t        |      }|sy ||vrt        dj	                  | |            y )NpidzPService '{s.name}' uses the PID namespace of service '{dep}' which is undefined.r~   rc   rC   r   r   r*   )rp   r   pid_moder   s       r1   validate_pid_moder      [    $$((/H3H=J& "F^FD
 	
 'r;   c                     | j                   j                  d      }|sy t        |      }|sy ||vrt        dj	                  | |            y )NipczPService '{s.name}' uses the IPC namespace of service '{dep}' which is undefined.r~   r   )rp   r   ipc_moder   s       r1   validate_ipc_moder      r   r;   c                     | j                   j                  dg       D ]4  }|j                  d      d   |vst        dj	                  | |             y )Nr   :r   zEService '{s.name}' has a link to service '{link}' which is undefined.)rn   r   )rc   rC   splitr   r*   )rp   r   r   s      r1   validate_linksr      s]    %%))'26 B::c?1]2$#Vn4V@B BBr;   c                     | j                   j                  di       }|j                         D ]"  }||vst        dj	                  | |             y )N
depends_onzAService '{s.name}' depends on service '{dep}' which is undefined.r~   )rc   rC   keysr   r*   )rp   r   depsr   s       r1   validate_depends_onr      sW      $$\26Diik 
]*$#Vn*VE r;   c                     | j                   j                  d      }|sy d|vr d|vrt        dj                  |             y y )Ncredential_specregistryrv   zQService '{s.name}' is missing 'credential_spec.file' or credential_spec.registry')rn   )rc   rC   r   r*   )rp   r   s     r1   validate_credential_specr      sU    $++//0ABO(V?-J ((.(@
 	
 .K(r;   c                     dj                  t        |       |      }|t        v r|dj                  t        |         z  }|S )Nz&Unsupported config option for {}: '{}'z (did you mean '{}'?))r*   path_stringDOCKER_CONFIG_HINTS)path	error_keymsgs      r1   get_unsupported_config_msgr   
  sC    
2
9
9+d:KY
WC''&--.A).LMMJr;   c                 8    | j                  d      rd| z   S d| z   S )N)ar0   iouzan za )
startswith)	json_types    r1   ra   ra     s'    56y  )r;   c                 
    | dv S )N)zconfig_schema_v1.jsonz#/properties/services )	schema_ids    r1   is_service_dict_schemar     s    JJJr;   c                 r   | j                   d   }t        |      rb| j                  dk(  rSdj                  t	        | j
                        D cg c]  }|rt        t        d |            s| c}d   t              S | j                  dk(  r|dk(  rt        |       }t        ||      S |j                  d      rMt        |       }dj                  |d	j                  | j                   d
   j                               t              S | j                  s dj                  | j                   t              S y y c c}w )NidadditionalPropertiesz:Invalid service name '{}' - only {} characters are allowedc                 8    t        j                  t        |        S N)r6   r7   VALID_NAME_CHARS)cs    r1   <lambda>z1handle_error_for_schema_with_id.<locals>.<lambda>"  s    bhh'7;; r;   r   z#/definitions/serviceconfig_schema_zInvalid top-level property "{key}". Valid top-level sections for this Compose file are: {properties}, and extensions starting with "x-".

{explanation}, 
properties)rd   r   explanationz{}

{})schemar   	validatorr*   rS   r/   anyfilterr   parse_key_from_error_msgr   r   joinr   r   r   message)errorr   r   r   invalid_config_keys        r1   handle_error_for_schema_with_idr     s0   T"Ii(U__@V-VKRRU^^, 1AV;Q> :Q  
 	
 00//!9%!@-d4FGG 01!9%!@FGMv&99U\\,%?%D%D%FG/ HN H zz$$U]]4GHH  1s   D4*D4c                    d }| j                   }| j                  dk(  r%d}t        |       \  }}|r|j                  |       n| j                  dk(  rd}t	        | j
                        }n| j                  dk(  rdj                  | j
                        }d}n| j                  dk(  rjt        | j
                  j                               d	   }d
j                  | j
                  |         }d}|j                  |       dj                  ||      }n2| j                  rt        | j                        }d}n| j                  rd}|r|j                  t        |      |      S | j                   S )NoneOfz{path} {msg}rY   z3{path} contains an invalid type, it should be {msg}requiredr   z%{path} is invalid, {msg} is required.dependenciesr   ,z{path} is invalid: {msg}z,when defining '{}' you must set '{}' as wellz{path} value {msg})r   r   )r   r   _parse_oneof_validatorappend!_parse_valid_types_from_validatorvalidator_valuer   rS   r   r*   causer.   r   r   )r   r   
msg_format	error_msg
config_keyrequired_keyss         r1   handle_generic_errorr   :  s?   JI'!#
 6u =
IKK
#	F	"J
5e6K6KL		J	&IIe334	<
	N	*%//4467:
!6!6z!BC/
JBII	 
$	/
	)
  k$&7Y GG==r;   c                     	 | j                   j                  d      d   S # t        $ rB | j                   j                  d      d   j                  d      d   j                  d      cY S w xY w)N'r   ( r   )r   r   
IndexErrorstrip)r   s    r1   r   r   c  sh    D}}""3'** D}}""3'*005a8>>sCCDs     AA+*A+c                 2    dj                  d | D              S )N.c              3   B   K   | ]  }t        |t              s|  y wr   )r5   r.   ).0r   s     r1   	<genexpr>zpath_string.<locals>.<genexpr>k  s     :!z!S'9A:s   )r   )r   s    r1   r   r   j  s    88:t:::r;   c                     t        | t              st        |       S t        |       dk(  rt        | d         S dj	                  dj                  t        | d         g| dd z         t        | d               S )zA validator value can be either an array of valid types or a string of
    a valid type. Parse the valid types and prefix with the correct article.
    r   r   z	{}, or {}r   )r5   rS   ra   lenr*   r   )r   s    r1   r   r   n  sw     i&"9--
9~"9Q<00		&y|45	!BGHIbM*, ,r;   c                 0   g }| j                   D ]g  }|j                  dk(  r't        |      \  }}t        |j                        |fc S |j                  dk(  rd|j
                  fc S |j                  dk(  r t        |      }ddj                  |      fc S |j                  dk(  r@|j                  rt        |j                        nddj                  |j                        fc S |j                  rYt        |j                        dj                  t        j                  |j                        t        |j                              fc S |j                  d	k(  sM|j                  |j                         j t        |      }dd
j                  |      fS )a  oneOf has multiple schemas, so we need to reason about which schema, sub
    schema or constraint the validation is failing on.
    Inspecting the context value of a ValidationError gives us information about
    which sub schema failed and which kind of error it is.
    r   r   Nr   z!contains unsupported option: '{}'uniqueItemsz;contains non-unique items, please remove duplicates from {}z6contains {}, which is an invalid type, it should be {}rY   z)contains an invalid type, it should be {})contextr   r   r   r   r   r   r*   r/   jsondumpsr   r   r   )r   typesr   _r   r   valid_typess          r1   r   r   }  sq    E== 2'1':LAyw||,i77
*'//** 66!9'!B=DDEWXYY--4\\GLL)tMTT$$&  <<GLL)HOOJJw//05g6M6MNP  &LL00192< 4E:K=DD[QRRr;   c                 &   |t         k(  rZd| j                  v rd| j                  v rdj                  |      S d| j                  v rd| j                  v rdj                  |      S d| j                  vr d| j                  vrdj                  |      S y y )NimagebuildzService {} has both an image and build path specified. A service can either be built to image or use an existing image, not both.
dockerfilezService {} has both an image and alternate Dockerfile. A service can either be built to image or use an existing image, not both.z]Service {} has neither an image nor a build context specified. At least one must be provided.)V1r/   r*   )r   rw   versions      r1   !process_service_constraint_errorsr     s    "}enn$ENN)B##)6,#79
 enn$)G##)6,#79
 enn$)F--3VL-A	C *G$r;   c                     t        | j                        }d| j                  v rt        | |      }|r|S t	        | |      S )Nr   )rS   r   r   r   r   )r   r   r   s      r1   process_config_schema_errorsr     s>    

Du||3E4@	t,,r;   c                     i }| j                         D ];  \  }}||t        |      <   t        |t              s%t	        |      |t        |      <   = |S )zH
        Non-string keys may break validator with patterned fields.
    )rb   r.   r5   rR   keys_to_str)rh   dkvs       r1   r   r     sT     	A!!# '1#a&	a#AAc!fI' Hr;   c                     t        |      }t        | j                        }t        g d      }t	        |t        t               |      |      }t        |j                  |      t        | j                         y )N)r   r3   r<   )resolverformat_checker)load_jsonschemar   rc   r   r   r   get_resolver_pathhandle_errorsiter_errorsr   r_   )rh   r   r   rc   r   r   s         r1   validate_against_config_schemar     si    W%F++,F"#KLN.0&9%'I f%$r;   c                     fd}t        j                        }t        |d   d   d         }t        |j	                  |       |d        y )Nc                 2    t        | j                        S r   )r   r   )errorsrh   rw   s    r1   handlerz-validate_service_constraints.<locals>.handler  s    0L+"5"57 	7r;   definitionsconstraintsservice)r   r   r   r   r   )rc   rw   rh   r   r   r   s    ``   r1   validate_service_constraintsr    sJ    7 [001F} 5m DY OPI)''/$?r;   c                     | j                   j                  d      }|sy |t        z  }t        |t              r|j                         st        d      y y )Ncpusz6cpus must have nine or less digits after decimal point)rc   rC   r
   r5   rU   
is_integerr   )rp   r  	nano_cpuss      r1   validate_cpur	    sX      $$V,D~%I)U#I,@,@,B DF 	F -C#r;   c                      t         j                  j                  t         j                  j                  t                    S r   )osr   dirnameabspath__file__r   r;   r1   get_schema_pathr    s"    77??277??8455r;   c                 r   d}| t         k(  rd}t        j                  j                  t	               dj                  |            }t        j                  j                  |      st        dj                  |t                    t        |      5 }t        j                  |      cd d d        S # 1 sw Y   y xY w)Ncompose_specconfig_schema_v1z{}.jsonz"Version in "{}" is unsupported. {})r   r  r   r   r  r*   existsr   r   openr   load)r   rB   r_   fhs       r1   r   r     s    D"}!ww|| H 77>>(# 0VH124 	4 
h 2yy}  s   B--B6c                      t               } t        j                  dk(  rd}| j                  dd      } nd}dj	                  ||       S )Nwin32z///\/z//z
file:{}{}/)r  sysplatformreplacer*   )schema_pathschemes     r1   r   r   	  sE    !#K
||w!))$4v{33r;   c                     t        | t              } | sydj                  fd| D              }t        dj	                  |rdj	                  |      nd|            )	zjsonschema returns an error tree full of information to explain what has
    gone wrong. Process each error and pull out relevant information and re-write
    helpful error messages that are relevant.
    )rd   N
c              3   .   K   | ]  } |        y wr   r   )r   r   format_error_funcs     r1   r   z handle_errors.<locals>.<genexpr>  s     Gu+E2Gs   z:The Compose file{file_msg} is invalid because:
{error_msg}z '{}'r(   )file_msgr   )sortedr.   r   r   r*   )r   r#  r_   r   s    `  r1   r   r     s_    
 F$F		GGGI
ELL19W^^H-r 	M 	!" "r;   c                    | j                   j                  di       }d|v rt        |d   t              rt	        |d         dk(  r$t        dj                  | j                              |d   d   dk(  r2t	        |      dkD  r$t        dj                  | j                              |d   d   dvr$t        d	j                  | j                              y y y )
Nhealthchecktestr   zDService "{}" defines an invalid healthcheck: "test" is an empty listNONEr   zbService "{}" defines an invalid healthcheck: "disable: true" cannot be combined with other options)r)  CMDz	CMD-SHELLzwService "{}" defines an invalid healthcheck: when "test" is a list the first item must be either NONE, CMD or CMD-SHELL)rc   rC   r5   rS   r   r   r*   rB   )rp   r'  s     r1   validate_healthcheckr+  $  s     ''++M2>KK,?!F{6"#q($*++,. .  #v-#k2BQ2F$H++,. .
  #+GG$]++,. . H "Gr;   )Gr   loggingr  r6   r  docker.utils.portsr   
jsonschemar   r   r   r   constr	   r   r
   r   r   r   sort_servicesr   	getLoggerrZ   logr   r   r8   VALID_IPV4_SEGr*   VALID_IPV4_ADDRr>   VALID_IPV6_SEGr   r   r?   
cls_checksr2   r:   r@   rK   r]   rf   ri   rt   rz   r   r   r   r   r   r   r   ra   r   r   r   r   r   r   r   r   r   r   r   r  r	  r  r   r   r   r+  r   r;   r1   <module>r7     s     	 	 
 ) & $ " & ( " & ' = g! " " ' 4 5299>9R<CCoC^ $ !$ FNoF>uuw%H * A B /B C -oF G	 P>+	/

F$

B	
KI>&RD;,&SRC(-	@F6"4" .r;   