Skip to content

Commit c47dddb

Browse files
committed
Implement override and reset analog to docker-compose (https://docs.docker.com/compose/compose-file/13-merge/)
Signed-off-by: Sebastian Sellmeier <mail@sebastian-sellmeier.de>
1 parent bce40c2 commit c47dddb

File tree

1 file changed

+66
-4
lines changed

1 file changed

+66
-4
lines changed

podman_compose.py

+66-4
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ def port_dict_to_str(port_desc):
694694

695695

696696
def norm_ports(ports_in):
697-
if not ports_in:
697+
if not ports_in or isinstance(ports_in, ResetTag):
698698
ports_in = []
699699
if isinstance(ports_in, str):
700700
ports_in = [ports_in]
@@ -1149,6 +1149,51 @@ def flat_deps(services, with_extends=False):
11491149
for name, srv in services.items():
11501150
rec_deps(services, name)
11511151

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
11521197

11531198
###################
11541199
# podman and compose classes
@@ -1293,6 +1338,9 @@ def normalize(compose):
12931338
"""
12941339
services = compose.get("services", None) or {}
12951340
for service in services.values():
1341+
if isinstance(service, ResetTag):
1342+
continue
1343+
12961344
normalize_service(service)
12971345
return compose
12981346

@@ -1330,6 +1378,8 @@ def rec_merge_one(target, source):
13301378
update target from source recursively
13311379
"""
13321380
done = set()
1381+
remove = set()
1382+
13331383
for key, value in source.items():
13341384
if key in target:
13351385
continue
@@ -1340,10 +1390,18 @@ def rec_merge_one(target, source):
13401390
continue
13411391
if key not in source:
13421392
continue
1393+
13431394
value2 = source[key]
1395+
13441396
if key in ("command", "entrypoint"):
13451397
target[key] = clone(value2)
13461398
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
13471405
if not isinstance(value2, type(value)):
13481406
value_type = type(value)
13491407
value2_type = type(value2)
@@ -1368,6 +1426,10 @@ def rec_merge_one(target, source):
13681426
rec_merge_one(value, value2)
13691427
else:
13701428
target[key] = value2
1429+
1430+
for key in remove:
1431+
del target[key]
1432+
13711433
return target
13721434

13731435

@@ -1629,13 +1691,13 @@ def _parse_compose_file(self):
16291691
compose["services"] = resolved_services
16301692
if not getattr(args, "no_normalize", None):
16311693
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")
16341696
self.yaml_hash = hashlib.sha256(merged_json_b).hexdigest()
16351697
compose["_dirname"] = dirname
16361698
# debug mode
16371699
if len(files) > 1:
1638-
log(" ** merged:\n", json.dumps(compose, indent=2))
1700+
log(" ** merged:\n", json.dumps(compose, indent=2, cls=ResetTagEncoder))
16391701
# ver = compose.get('version', None)
16401702

16411703
if not project_name:

0 commit comments

Comments
 (0)