inputs: pre-defined input paths
Instead of bind-mounting each individual input into the container,
create a temporary directory that is used by all inputs and bind-
mount this to the well known location ("/run/osbuild/inputs"). The
temporary directory is then passed to the input so that it can
make the requested resources available relative to that directory.
This is enforced by the common input handling code.
Additionally, pass the well known input path via a new "paths" key
to the arguments dictionary passed to the stage.
This commit is contained in:
parent
47fefe7e2d
commit
08bc9ab7d8
6 changed files with 45 additions and 28 deletions
|
|
@ -80,10 +80,10 @@ SCHEMA = r"""
|
|||
def main():
|
||||
args = json.load(sys.stdin)
|
||||
refs = args["refs"]
|
||||
target = args["target"]
|
||||
|
||||
store = StoreClient(connect_to=args["api"]["store"])
|
||||
source = store.source("org.osbuild.files")
|
||||
output = store.mkdtemp(prefix="files-input-")
|
||||
|
||||
for checksum in refs:
|
||||
try:
|
||||
|
|
@ -91,7 +91,7 @@ def main():
|
|||
[
|
||||
"ln",
|
||||
f"{source}/{checksum}",
|
||||
f"{output}/{checksum}",
|
||||
f"{target}/{checksum}",
|
||||
],
|
||||
check=True,
|
||||
)
|
||||
|
|
@ -100,9 +100,9 @@ def main():
|
|||
return 1
|
||||
|
||||
reply = {
|
||||
"path": output,
|
||||
"path": target,
|
||||
"data": {
|
||||
"refs": refs
|
||||
"refs": refs
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ it to the stage.
|
|||
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
from osbuild.objectstore import StoreClient
|
||||
import uuid
|
||||
|
||||
|
||||
SCHEMA = """
|
||||
|
|
@ -21,10 +21,12 @@ SCHEMA = """
|
|||
def main():
|
||||
args = json.load(sys.stdin)
|
||||
refs = args["refs"]
|
||||
target = args["target"]
|
||||
|
||||
store = StoreClient(connect_to=args["api"]["store"])
|
||||
uid = str(uuid.uuid4())
|
||||
path = os.path.join(target, uid)
|
||||
os.makedirs(path)
|
||||
|
||||
path = store.mkdtemp(prefix="empty")
|
||||
data = {"path": path, "data": {"refs": refs}}
|
||||
json.dump(data, sys.stdout)
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -105,10 +105,10 @@ def export(checksums, cache, output):
|
|||
def main():
|
||||
args = json.load(sys.stdin)
|
||||
refs = args["refs"]
|
||||
target = args["target"]
|
||||
|
||||
origin = args["origin"]
|
||||
store = StoreClient(connect_to=args["api"]["store"])
|
||||
output = store.mkdtemp(prefix="ostree-output")
|
||||
|
||||
if origin == "org.osbuild.pipeline":
|
||||
for ref, options in refs.items():
|
||||
|
|
@ -116,10 +116,10 @@ def main():
|
|||
with open(os.path.join(source, "compose.json"), "r") as f:
|
||||
compose = json.load(f)
|
||||
commit_id = compose["ostree-commit"]
|
||||
export({commit_id: options}, source, output)
|
||||
export({commit_id: options}, source, target)
|
||||
else:
|
||||
source = store.source("org.osbuild.ostree")
|
||||
export(refs, source, output)
|
||||
export(refs, source, target)
|
||||
|
||||
return 0
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ def error(msg):
|
|||
def main():
|
||||
args = json.load(sys.stdin)
|
||||
refs = args["refs"]
|
||||
target = args["target"]
|
||||
|
||||
# input verification *must* have been done via schema
|
||||
# verification. It is expected that origin is a pipeline
|
||||
|
|
@ -68,15 +69,13 @@ def main():
|
|||
|
||||
store = StoreClient(connect_to=args["api"]["store"])
|
||||
|
||||
if not pid:
|
||||
path = store.mkdtemp(prefix="empty")
|
||||
else:
|
||||
path = store.read_tree(pid)
|
||||
if pid:
|
||||
path = store.read_tree_at(pid, target)
|
||||
|
||||
if not path:
|
||||
error(f"Could not find pipeline with id '{pid}'")
|
||||
|
||||
json.dump({"path": path}, sys.stdout)
|
||||
json.dump({"path": target}, sys.stdout)
|
||||
return 0
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import subprocess
|
|||
|
||||
from typing import Dict, Optional, Tuple
|
||||
|
||||
from osbuild.util.types import PathLike
|
||||
from .objectstore import StoreServer
|
||||
|
||||
|
||||
|
|
@ -58,13 +59,19 @@ class Input:
|
|||
m.update(json.dumps(self.options, sort_keys=True).encode())
|
||||
return m.hexdigest()
|
||||
|
||||
def run(self, storeapi: StoreServer) -> Tuple[str, Dict]:
|
||||
def run(self, storeapi: StoreServer, root: PathLike) -> Tuple[str, Dict]:
|
||||
name = self.info.name
|
||||
|
||||
target = os.path.join(root, self.name)
|
||||
os.makedirs(target)
|
||||
|
||||
msg = {
|
||||
# mandatory bits
|
||||
"origin": self.origin,
|
||||
"refs": self.refs,
|
||||
|
||||
"target": target,
|
||||
|
||||
# global options
|
||||
"options": self.options,
|
||||
|
||||
|
|
@ -101,6 +108,11 @@ class Input:
|
|||
if r.returncode != 0:
|
||||
raise RuntimeError(f"{name}: error {r.returncode}")
|
||||
|
||||
path, data = reply["path"], reply.get("data", {})
|
||||
path = reply["path"]
|
||||
|
||||
return path, data
|
||||
if not path.startswith(root):
|
||||
raise RuntimeError(f"returned {path} has wrong prefix")
|
||||
|
||||
reply["path"] = os.path.relpath(path, root)
|
||||
|
||||
return reply
|
||||
|
|
|
|||
|
|
@ -70,30 +70,34 @@ class Stage:
|
|||
build_root = buildroot.BuildRoot(build_tree, runner, libdir, store.tmp)
|
||||
cm.enter_context(build_root)
|
||||
|
||||
inputs_tmpdir = store.tempdir(prefix="inputs-")
|
||||
inputs_tmpdir = cm.enter_context(inputs_tmpdir)
|
||||
inputs_mapped = "/run/osbuild/inputs"
|
||||
inputs = {}
|
||||
|
||||
args = {
|
||||
"tree": "/run/osbuild/tree",
|
||||
"options": self.options,
|
||||
"inputs": {},
|
||||
"paths": {
|
||||
"inputs": inputs_mapped
|
||||
},
|
||||
"inputs": inputs,
|
||||
"meta": {
|
||||
"id": self.id
|
||||
}
|
||||
}
|
||||
|
||||
ro_binds = [
|
||||
f"{self.info.path}:/run/osbuild/bin/{self.name}"
|
||||
f"{self.info.path}:/run/osbuild/bin/{self.name}",
|
||||
f"{inputs_tmpdir}:{inputs_mapped}"
|
||||
]
|
||||
|
||||
storeapi = objectstore.StoreServer(store)
|
||||
cm.enter_context(storeapi)
|
||||
|
||||
for key, ip in self.inputs.items():
|
||||
path, data = ip.run(storeapi)
|
||||
|
||||
# bind mount the returned path into the container
|
||||
mapped = f"/run/osbuild/inputs/{key}"
|
||||
ro_binds += [f"{path}:{mapped}"]
|
||||
|
||||
args["inputs"][key] = {"path": mapped, "data": data}
|
||||
data = ip.run(storeapi, inputs_tmpdir)
|
||||
inputs[key] = data
|
||||
|
||||
api = API(args, monitor)
|
||||
build_root.register_api(api)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue