osbuild: add --output-directory=DIR
Add a new output-directory argument which specifies where to store
result objects. For now, this is purely optional and simply copies from
the old `output_id` into the specified directory. This allows a
backwards compatible transition towards removing any external access to
the osbuild cache.
Note that this has still lots of room for improvements:
* We only support assembler-output for now, but we could also easily
support entire trees as output, in case no assembler was selected.
Alternatively, we could introduce a "copy" assembler, that just
outputs the input tree.
* This parameter is optional, but should really be mandatory. There
is little reason to have the default behavior just dropping any
generated content. This would be a breaking change, though.
* We could move data out of a temporary object-store entry, rather
than copy it. But again, for backwards-compatibility, we leave the
latest store-object intact and do not move things out of it.
* We could now transition towards never committing anything to the
store, not even output IDs, unless explicitly checkpointed.
This commit is contained in:
parent
ef3f601d05
commit
551faf2d61
3 changed files with 28 additions and 19 deletions
|
|
@ -50,6 +50,7 @@ is not listed here, **osbuild** will deny startup and exit with an error.
|
||||||
--checkpoint=CHECKPOINT stage to commit to the object store during
|
--checkpoint=CHECKPOINT stage to commit to the object store during
|
||||||
build (can be passed multiple times)
|
build (can be passed multiple times)
|
||||||
--json output results in JSON format
|
--json output results in JSON format
|
||||||
|
--output-directory=DIR directory where result objects are stored
|
||||||
|
|
||||||
MANIFEST
|
MANIFEST
|
||||||
========
|
========
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,8 @@ def main():
|
||||||
help="stage to commit to the object store during build (can be passed multiple times)")
|
help="stage to commit to the object store during build (can be passed multiple times)")
|
||||||
parser.add_argument("--json", action="store_true",
|
parser.add_argument("--json", action="store_true",
|
||||||
help="output results in JSON format")
|
help="output results in JSON format")
|
||||||
|
parser.add_argument("--output-directory", metavar="DIRECTORY", type=os.path.abspath,
|
||||||
|
help="directory where result objects are stored")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.manifest_path == "-":
|
if args.manifest_path == "-":
|
||||||
|
|
@ -91,7 +93,8 @@ def main():
|
||||||
args.store,
|
args.store,
|
||||||
interactive=not args.json,
|
interactive=not args.json,
|
||||||
libdir=args.libdir,
|
libdir=args.libdir,
|
||||||
secrets=secrets
|
secrets=secrets,
|
||||||
|
output_directory=args.output_directory
|
||||||
)
|
)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print()
|
print()
|
||||||
|
|
|
||||||
|
|
@ -340,22 +340,22 @@ class Pipeline:
|
||||||
results["output_id"] = self.output_id
|
results["output_id"] = self.output_id
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def run(self, store, interactive=False, libdir=None, secrets=None):
|
def run(self, store, interactive=False, libdir=None, secrets=None, output_directory=None):
|
||||||
os.makedirs("/run/osbuild", exist_ok=True)
|
os.makedirs("/run/osbuild", exist_ok=True)
|
||||||
results = {}
|
results = {}
|
||||||
|
|
||||||
with objectstore.ObjectStore(store) as object_store:
|
with objectstore.ObjectStore(store) as object_store:
|
||||||
# if the final result is already in the store, exit
|
# If the final result is already in the store, no need to attempt
|
||||||
# early and don't attempt to build the tree, which
|
# building it. Just fetch the cached information. If the associated
|
||||||
# in turn might not be in the store and would in that
|
# tree exists, we return it as well, but we do not care if it is
|
||||||
# case be build but not be used
|
# missing, since it is not a mandatory part of the result and would
|
||||||
|
# usually be needless overhead.
|
||||||
if object_store.contains(self.output_id):
|
if object_store.contains(self.output_id):
|
||||||
results = {"output_id": self.output_id,
|
results = {"output_id": self.output_id,
|
||||||
"success": True}
|
"success": True}
|
||||||
if object_store.contains(self.tree_id):
|
if object_store.contains(self.tree_id):
|
||||||
results["tree_id"] = self.tree_id
|
results["tree_id"] = self.tree_id
|
||||||
return results
|
else:
|
||||||
|
|
||||||
results, build_tree, tree = self.build_stages(object_store,
|
results, build_tree, tree = self.build_stages(object_store,
|
||||||
interactive,
|
interactive,
|
||||||
libdir,
|
libdir,
|
||||||
|
|
@ -372,6 +372,11 @@ class Pipeline:
|
||||||
|
|
||||||
results.update(r) # This will also update 'success'
|
results.update(r) # This will also update 'success'
|
||||||
|
|
||||||
|
if results["success"] and output_directory is not None:
|
||||||
|
output_source = object_store.resolve_ref(results["output_id"])
|
||||||
|
if output_source is not None:
|
||||||
|
subprocess.run(["cp", "--reflink=auto", "-a", f"{output_source}/.", output_directory], check=True)
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue