@@ -694,7 +694,7 @@ def port_dict_to_str(port_desc):
694
694
695
695
696
696
def norm_ports (ports_in ):
697
- if not ports_in :
697
+ if not ports_in or isinstance ( ports_in , ResetTag ) :
698
698
ports_in = []
699
699
if isinstance (ports_in , str ):
700
700
ports_in = [ports_in ]
@@ -1149,6 +1149,51 @@ def flat_deps(services, with_extends=False):
1149
1149
for name , srv in services .items ():
1150
1150
rec_deps (services , name )
1151
1151
1152
+ ###################
1153
+ # Override and reset tags
1154
+ ###################
1155
+
1156
+ class OverrideTag (yaml .YAMLObject ):
1157
+ yaml_dumper = yaml .Dumper
1158
+ yaml_loader = yaml .SafeLoader
1159
+ yaml_tag = u'!override'
1160
+
1161
+ def __init__ (self , value ):
1162
+ values = list ()
1163
+
1164
+ for item in value :
1165
+ values .append (item .value )
1166
+
1167
+ self .value = values
1168
+
1169
+ @classmethod
1170
+ def from_yaml (cls , loader , node ):
1171
+ return OverrideTag (node .value )
1172
+
1173
+ @classmethod
1174
+ def to_yaml (cls , dumper , data ):
1175
+ return dumper .represent_scalar (cls .yaml_tag , data .value )
1176
+
1177
+ class ResetTag (yaml .YAMLObject ):
1178
+ yaml_dumper = yaml .Dumper
1179
+ yaml_loader = yaml .SafeLoader
1180
+ yaml_tag = u'!reset'
1181
+
1182
+ @classmethod
1183
+ def toJSON (self ):
1184
+ return self .yaml_tag
1185
+
1186
+ @classmethod
1187
+ def from_yaml (cls , loader , node ):
1188
+ return ResetTag ()
1189
+
1190
+ @classmethod
1191
+ def to_yaml (cls , dumper , data ):
1192
+ return dumper .represent_scalar (cls .yaml_tag , '' )
1193
+
1194
+ class ResetTagEncoder (json .JSONEncoder ):
1195
+ def default (self , o ):
1196
+ return o .yaml_tag
1152
1197
1153
1198
###################
1154
1199
# podman and compose classes
@@ -1293,6 +1338,9 @@ def normalize(compose):
1293
1338
"""
1294
1339
services = compose .get ("services" , None ) or {}
1295
1340
for service in services .values ():
1341
+ if isinstance (service , ResetTag ):
1342
+ continue
1343
+
1296
1344
normalize_service (service )
1297
1345
return compose
1298
1346
@@ -1330,6 +1378,8 @@ def rec_merge_one(target, source):
1330
1378
update target from source recursively
1331
1379
"""
1332
1380
done = set ()
1381
+ remove = set ()
1382
+
1333
1383
for key , value in source .items ():
1334
1384
if key in target :
1335
1385
continue
@@ -1340,10 +1390,18 @@ def rec_merge_one(target, source):
1340
1390
continue
1341
1391
if key not in source :
1342
1392
continue
1393
+
1343
1394
value2 = source [key ]
1395
+
1344
1396
if key in ("command" , "entrypoint" ):
1345
1397
target [key ] = clone (value2 )
1346
1398
continue
1399
+ if isinstance (value , ResetTag ) or isinstance (value2 , ResetTag ):
1400
+ remove .add (key )
1401
+ continue
1402
+ if isinstance (value , OverrideTag ) or isinstance (value2 , OverrideTag ):
1403
+ target [key ] = clone (value .value ) if isinstance (value , OverrideTag ) else clone (value2 .value )
1404
+ continue
1347
1405
if not isinstance (value2 , type (value )):
1348
1406
value_type = type (value )
1349
1407
value2_type = type (value2 )
@@ -1368,6 +1426,10 @@ def rec_merge_one(target, source):
1368
1426
rec_merge_one (value , value2 )
1369
1427
else :
1370
1428
target [key ] = value2
1429
+
1430
+ for key in remove :
1431
+ del target [key ]
1432
+
1371
1433
return target
1372
1434
1373
1435
@@ -1629,13 +1691,13 @@ def _parse_compose_file(self):
1629
1691
compose ["services" ] = resolved_services
1630
1692
if not getattr (args , "no_normalize" , None ):
1631
1693
compose = normalize_final (compose , self .dirname )
1632
- self .merged_yaml = yaml .safe_dump (compose )
1633
- merged_json_b = json .dumps (compose , separators = ("," , ":" )).encode ("utf-8" )
1694
+ self .merged_yaml = yaml .dump (compose )
1695
+ merged_json_b = json .dumps (compose , separators = ("," , ":" ), cls = ResetTagEncoder ).encode ("utf-8" )
1634
1696
self .yaml_hash = hashlib .sha256 (merged_json_b ).hexdigest ()
1635
1697
compose ["_dirname" ] = dirname
1636
1698
# debug mode
1637
1699
if len (files ) > 1 :
1638
- log (" ** merged:\n " , json .dumps (compose , indent = 2 ))
1700
+ log (" ** merged:\n " , json .dumps (compose , indent = 2 , cls = ResetTagEncoder ))
1639
1701
# ver = compose.get('version', None)
1640
1702
1641
1703
if not project_name :
0 commit comments