Skip to content

Commit 67e5ce0

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 <[email protected]>
1 parent bce40c2 commit 67e5ce0

File tree

1 file changed

+82
-2
lines changed

1 file changed

+82
-2
lines changed

podman_compose.py

+82-2
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,47 @@ 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, '')
11521193

11531194
###################
11541195
# podman and compose classes
@@ -1245,6 +1286,14 @@ def volume_ls(self, proj=None):
12451286

12461287

12471288
def normalize_service(service, sub_dir=""):
1289+
if isinstance(service, ResetTag):
1290+
return service
1291+
1292+
if isinstance(service, OverrideTag):
1293+
tagObj = service
1294+
service = tagObj.value
1295+
print(subdir)
1296+
12481297
if "build" in service:
12491298
build = service["build"]
12501299
if is_str(build):
@@ -1284,7 +1333,12 @@ def normalize_service(service, sub_dir=""):
12841333
if is_str(extends):
12851334
extends = {"service": extends}
12861335
service["extends"] = extends
1287-
return service
1336+
1337+
try:
1338+
tagObj.value = serivce
1339+
return tagObj
1340+
except NameError:
1341+
return service
12881342

12891343

12901344
def normalize(compose):
@@ -1330,6 +1384,8 @@ def rec_merge_one(target, source):
13301384
update target from source recursively
13311385
"""
13321386
done = set()
1387+
remove = set()
1388+
13331389
for key, value in source.items():
13341390
if key in target:
13351391
continue
@@ -1339,17 +1395,37 @@ def rec_merge_one(target, source):
13391395
if key in done:
13401396
continue
13411397
if key not in source:
1398+
if isinstance(value, ResetTag):
1399+
log("INFO: Unneeded !reset found for [{key}]")
1400+
remove.add(key)
1401+
1402+
if isinstance(value, OverrideTag):
1403+
log("INFO: Unneeded !override found for [{key}] with value '{value}'")
1404+
target[key] = clone(value.value)
1405+
13421406
continue
1407+
13431408
value2 = source[key]
1409+
1410+
if isinstance(value, ResetTag) or isinstance(value2, ResetTag):
1411+
remove.add(key)
1412+
continue
1413+
1414+
if isinstance(value, OverrideTag) or isinstance(value2, OverrideTag):
1415+
target[key] = clone(value.value) if isinstance(value, OverrideTag) else clone(value2.value)
1416+
continue
1417+
13441418
if key in ("command", "entrypoint"):
13451419
target[key] = clone(value2)
13461420
continue
1421+
13471422
if not isinstance(value2, type(value)):
13481423
value_type = type(value)
13491424
value2_type = type(value2)
13501425
raise ValueError(
13511426
f"can't merge value of [{key}] of type {value_type} and {value2_type}"
13521427
)
1428+
13531429
if is_list(value2):
13541430
if key == "volumes":
13551431
# clean duplicate mount targets
@@ -1368,6 +1444,10 @@ def rec_merge_one(target, source):
13681444
rec_merge_one(value, value2)
13691445
else:
13701446
target[key] = value2
1447+
1448+
for key in remove:
1449+
del target[key]
1450+
13711451
return target
13721452

13731453

@@ -1629,7 +1709,7 @@ def _parse_compose_file(self):
16291709
compose["services"] = resolved_services
16301710
if not getattr(args, "no_normalize", None):
16311711
compose = normalize_final(compose, self.dirname)
1632-
self.merged_yaml = yaml.safe_dump(compose)
1712+
self.merged_yaml = yaml.dump(compose)
16331713
merged_json_b = json.dumps(compose, separators=(",", ":")).encode("utf-8")
16341714
self.yaml_hash = hashlib.sha256(merged_json_b).hexdigest()
16351715
compose["_dirname"] = dirname

0 commit comments

Comments
 (0)