pipeline,api: write metadata directly

Instead of transmitting stage metadata over a socket and then
writing it via `Object.meta.write`, use the latter and bind
mount the corresponding file into the stage so it can directly
be written to from the stage. Change `api.metadata` to do so,
which means that this change is transparent for the stages.
This commit is contained in:
Christian Kellner 2022-11-25 16:36:32 +01:00
parent 8b638562d1
commit 809c9e7828
3 changed files with 19 additions and 39 deletions

View file

@ -142,15 +142,8 @@ class API(BaseAPI):
def __init__(self, *, socket_address=None):
super().__init__(socket_address)
self.metadata = {}
self.error = None
def _set_metadata(self, message, fds):
fd = message["metadata"]
with os.fdopen(fds.steal(fd), encoding="utf8") as f:
data = json.load(f)
self.metadata.update(data)
def _get_exception(self, message):
self.error = {
"type": "exception",
@ -158,9 +151,7 @@ class API(BaseAPI):
}
def _message(self, msg, fds, sock):
if msg["method"] == 'add-metadata':
self._set_metadata(msg, fds)
elif msg["method"] == 'exception':
if msg["method"] == 'exception':
self._get_exception(msg)
@ -200,18 +191,8 @@ def arguments(path="/run/osbuild/api/arguments"):
return data
def metadata(data: Dict, path="/run/osbuild/api/osbuild"):
def metadata(data: Dict, path="/run/osbuild/meta"):
"""Update metadata for the current module"""
def data_to_file():
with tempfile.TemporaryFile() as f:
f.write(json.dumps(data).encode('utf8'))
# re-open the file to get a read-only file descriptor
return open(f"/proc/self/fd/{f.fileno()}", "r", encoding="utf8")
with jsoncomm.Socket.new_client(path) as client, data_to_file() as f:
msg = {
"method": "add-metadata",
"metadata": 0
}
client.send(msg, fds=[f.fileno()])
with open(path, "w", encoding="utf8") as f:
json.dump(data, f, indent=2)

View file

@ -185,6 +185,10 @@ class Stage:
"mounts": mounts,
}
meta = cm.enter_context(
tree.meta.write(self.id)
)
ro_binds = [
f"{self.info.path}:/run/osbuild/bin/{self.name}",
f"{inputs_tmpdir}:{inputs_mapped}",
@ -193,6 +197,7 @@ class Stage:
binds = [
os.fspath(tree) + ":/run/osbuild/tree",
meta.name + ":/run/osbuild/meta",
f"{mounts_tmpdir}:{mounts_mapped}"
]
@ -235,9 +240,6 @@ class Stage:
readonly_binds=ro_binds,
extra_env=extra_env)
if r.returncode == 0:
tree.meta.set(self.id, api.metadata)
return BuildResult(self, r.returncode, r.output, api.error)

View file

@ -2,8 +2,10 @@
# Test for API infrastructure
#
import json
import multiprocessing as mp
import os
import pathlib
import tempfile
import unittest
@ -99,19 +101,14 @@ class TestAPI(unittest.TestCase):
# Check that `api.metadata` leads to `API.metadata` being
# set correctly
tmpdir = self.tmp.name
path = os.path.join(tmpdir, "osbuild-api")
path = pathlib.Path(tmpdir, "metadata")
path.touch()
def metadata(path):
data = {"meta": "42"}
osbuild.api.metadata(data, path=path)
return 0
data = {"meta": "42"}
osbuild.api.metadata(data, path=path)
with open(path, "r", encoding="utf8") as f:
metadata = json.load(f)
api = osbuild.api.API(socket_address=path)
with api:
p = mp.Process(target=metadata, args=(path, ))
p.start()
p.join()
self.assertEqual(p.exitcode, 0)
metadata = api.metadata # pylint: disable=no-member
assert metadata
self.assertEqual(metadata, {"meta": "42"})
self.assertEqual(metadata, data)