@@ -102,6 +102,27 @@ def strverscmp_lt(a, b):
102
102
return a_ls < b_ls
103
103
104
104
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
+
105
126
def parse_short_mount (mount_str , basedir ):
106
127
mount_a = mount_str .split (":" )
107
128
mount_opt_dict = {}
@@ -987,25 +1008,46 @@ def flat_deps(services, with_extends=False):
987
1008
create dependencies "_deps" or update it recursively for all services
988
1009
"""
989
1010
for name , srv in services .items ():
990
- deps = set ()
991
- srv ["_deps" ] = deps
1011
+ deps = {}
992
1012
if with_extends :
993
1013
ext = srv .get ("extends" , {}).get ("service" , None )
994
1014
if ext :
995
1015
if ext != name :
996
- deps . add ( ext )
1016
+ deps [ ext ] = DependsCondition . STARTED
997
1017
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
998
1020
deps_ls = srv .get ("depends_on" , None ) or []
999
1021
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 }
1001
1025
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 }
1004
1040
# 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
1005
1043
links_ls = srv .get ("links" , None ) or []
1006
1044
if not is_list (links_ls ):
1007
1045
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
1009
1051
for name , srv in services .items ():
1010
1052
rec_deps (services , name )
1011
1053
@@ -1922,7 +1964,7 @@ def get_excluded(compose, args):
1922
1964
if args .services :
1923
1965
excluded = set (compose .services )
1924
1966
for service in args .services :
1925
- excluded -= compose .services [service ]["_deps" ]
1967
+ excluded -= set ( compose .services [service ]["_deps" ]. keys ())
1926
1968
excluded .discard (service )
1927
1969
log ("** excluding: " , excluded )
1928
1970
return excluded
0 commit comments