debian-forge/inputs/org.osbuild.ostree
Christian Kellner 99abc1373d inputs: support array of objects references
This extends the possible ways of passing references to inputs. The
current ways possible are:
 1) "plain references", an array of strings:
    ["ref1", "ref2", ...]
 2) "object references", a mapping of keys to objects:
    {"ref1": { <options> }, "ref2": { <options> }, ...}

This patch adds a new way:
  3) "array of object references":
    [{"id": "ref1", "options": { ... }}, {"id": ... }, ]

While osbuild promises to preserves the order for "object references"
not all JSON serialization libraries preserve the order since the
JSON specification does leave this up to the implementation.

The new "array of object references" thus allows for specifying the
references together with reference specific options and this in a
specific order.

Additionally this paves the way for specifying the same input twice,
e.g. in the case of the `org.osbuild.files` input where a pipeline
could then be specified twice with different files. This needs core
rework though, since internally we use dictionaries right now.
2022-04-21 16:39:58 +02:00

153 lines
3.5 KiB
Python
Executable file

#!/usr/bin/python3
"""
Inputs for ostree commits
Pull the commits specified by `references` into a newly created
repository. Optionally, if `ref` was specified, create an new
reference for that commit.
The returned data in `refs` is a dictionary where the keys are
commit ids and the values are dictionaries. The latter will
contain `ref` it was specified.
"""
import os
import json
import sys
import subprocess
from osbuild import inputs
SCHEMA = """
"definitions": {
"options": {
"type": "object",
"additionalProperties": false,
"properties": {
"ref": {
"type": "string",
"description": "OSTree reference to create for this commit"
}
}
}
},
"additionalProperties": false,
"required": ["type", "origin", "references"],
"properties": {
"type": {
"enum": ["org.osbuild.ostree"]
},
"origin": {
"description": "The origin of the input (pipeline or source)",
"type": "string",
"enum": ["org.osbuild.source", "org.osbuild.pipeline"]
},
"references": {
"description": "Commit identifier",
"oneOf": [{
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
}, {
"type": "object",
"additionalProperties": false,
"minProperties": 1,
"patternProperties": {
".*": {
"$ref": "#/definitions/options"
}
}
}, {
"type": "array",
"additionalItems": false,
"minItems": 1,
"maxItems": 1,
"items": [{
"type": "object",
"additionalProperties": false,
"required": ["id"],
"properties": {
"id": {
"type": "string"
},
"options": {
"$ref": "#/definitions/options"
}
}
}]
}]
}
}
"""
def ostree(*args, _input=None, **kwargs):
args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()]
print("ostree " + " ".join(args), file=sys.stderr)
subprocess.run(["ostree"] + args,
encoding="utf-8",
stdout=sys.stderr,
input=_input,
check=True)
def export(checksums, cache, output):
repo_cache = os.path.join(cache, "repo")
repo_out = os.path.join(output, "repo")
ostree("init", mode="archive", repo=repo_out)
refs = {}
for commit, options in checksums.items():
# Transfer the commit: remote → cache
print(f"exporting {commit}", file=sys.stderr)
ostree("pull-local", repo_cache, commit,
repo=repo_out)
ref = options.get("ref")
if ref:
ostree("refs", "--create", ref, commit,
repo=repo_out)
refs[commit] = options
reply = {
"path": repo_out,
"data": {
"refs": refs
}
}
return reply
class OSTreeInput(inputs.InputService):
def map(self, store, origin, refs, target, _options):
if origin == "org.osbuild.pipeline":
for ref, options in refs.items():
source = store.read_tree(ref)
with open(os.path.join(source, "compose.json"), "r") as f:
compose = json.load(f)
commit_id = compose["ostree-commit"]
reply = export({commit_id: options}, source, target)
else:
source = store.source("org.osbuild.ostree")
reply = export(refs, source, target)
return reply
def main():
service = OSTreeInput.from_args(sys.argv[1:])
service.main()
if __name__ == '__main__':
main()