@@ -102,6 +102,27 @@ def strverscmp_lt(a, b):
102102 return a_ls < b_ls
103103
104104
105+ class DependsCondition : # pylint: disable=too-few-public-methods
106+ # enum for possible types of depends_on conditions
107+ # see https://github.com/compose-spec/compose-spec/blob/master/spec.md#long-syntax-1
108+ STARTED = 0
109+ HEALTHY = 1
110+ COMPLETED = 2
111+
112+ @classmethod
113+ def to_enum (cls , condition ):
114+ """
115+ Converts and returns a condition value into a valid enum value.
116+ """
117+ if condition == "service_healthy" :
118+ return cls .HEALTHY
119+ if condition == "service_completed_successfully" :
120+ return cls .COMPLETED
121+ # use cls.STARTED as a catch-all value even
122+ # if the condition value is not within spec
123+ return cls .STARTED
124+
125+
105126def parse_short_mount (mount_str , basedir ):
106127 mount_a = mount_str .split (":" )
107128 mount_opt_dict = {}
@@ -987,25 +1008,46 @@ def flat_deps(services, with_extends=False):
9871008 create dependencies "_deps" or update it recursively for all services
9881009 """
9891010 for name , srv in services .items ():
990- deps = set ()
991- srv ["_deps" ] = deps
1011+ deps = {}
9921012 if with_extends :
9931013 ext = srv .get ("extends" , {}).get ("service" , None )
9941014 if ext :
9951015 if ext != name :
996- deps . add ( ext )
1016+ deps [ ext ] = DependsCondition . STARTED
9971017 continue
1018+ # NOTE: important that the get call is kept as-is, since depends_on
1019+ # can be an empty string and in that case we want to have an empty list
9981020 deps_ls = srv .get ("depends_on" , None ) or []
9991021 if is_str (deps_ls ):
1000- deps_ls = [deps_ls ]
1022+ # depends_on: "foo"
1023+ # treat as condition: service_started
1024+ deps_ls = {deps_ls : DependsCondition .STARTED }
10011025 elif is_dict (deps_ls ):
1002- deps_ls = list (deps_ls .keys ())
1003- deps .update (deps_ls )
1026+ # depends_on:
1027+ # foo:
1028+ # condition: service_xxx
1029+ tmp = {}
1030+ for service , condition in deps_ls .items ():
1031+ condition = DependsCondition .to_enum (condition .get ("condition" ))
1032+ tmp [service ] = condition
1033+ deps_ls = tmp
1034+ else :
1035+ # depends_on:
1036+ # - foo
1037+ # treat as condition: service_started
1038+ deps_ls = {dep : DependsCondition .STARTED for dep in deps_ls }
1039+ deps = {** deps , ** deps_ls }
10041040 # parse link to get service name and remove alias
1041+ # NOTE: important that the get call is kept as-is, since links can
1042+ # be an empty string and in that case we want to have an empty list
10051043 links_ls = srv .get ("links" , None ) or []
10061044 if not is_list (links_ls ):
10071045 links_ls = [links_ls ]
1008- deps .update ([(c .split (":" )[0 ] if ":" in c else c ) for c in links_ls ])
1046+ deps = {
1047+ ** deps ,
1048+ ** {c .split (":" )[0 ]: DependsCondition .STARTED for c in links_ls },
1049+ }
1050+ srv ["_deps" ] = deps
10091051 for name , srv in services .items ():
10101052 rec_deps (services , name )
10111053
@@ -1922,7 +1964,7 @@ def get_excluded(compose, args):
19221964 if args .services :
19231965 excluded = set (compose .services )
19241966 for service in args .services :
1925- excluded -= compose .services [service ]["_deps" ]
1967+ excluded -= set ( compose .services [service ]["_deps" ]. keys ())
19261968 excluded .discard (service )
19271969 log ("** excluding: " , excluded )
19281970 return excluded
0 commit comments