def load_assembler(description: Dict, index: Index, manifest: Manifest): pipeline = manifest["tree"] build, base, runner = pipeline.build, pipeline.id, pipeline.runner name, options = description["name"], description.get("options", {}) # Add a pipeline with one stage for our assembler pipeline = manifest.add_pipeline("assembler", runner, build) info = index.get_module_info("Assembler", name) stage = pipeline.add_stage(info, options, {}) info = index.get_module_info("Input", "org.osbuild.tree") ip = stage.add_input("tree", info, "org.osbuild.pipeline") ip.add_reference(base) return pipeline
def load_input(name: str, description: Dict, index: Index, stage: Stage, manifest: Manifest, source_refs: set): input_type = description["type"] origin = description["origin"] options = description.get("options", {}) info = index.get_module_info("Input", input_type) ip = stage.add_input(name, info, origin, options) refs = description.get("references", {}) if isinstance(refs, list): refs = {r: {} for r in refs} if origin == "org.osbuild.pipeline": resolved = {} for r, desc in refs.items(): if not r.startswith("name:"): continue target = resolve_ref(r, manifest) resolved[target] = desc refs = resolved elif origin == "org.osbuild.source": unknown_refs = set(refs.keys()) - source_refs if unknown_refs: raise ValueError(f"Unknown source reference(s) {unknown_refs}") for r, desc in refs.items(): ip.add_reference(r, desc)
def load_stage(description: Dict, index: Index, pipeline: Pipeline, manifest: Manifest): stage_type = description["type"] opts = description.get("options", {}) info = index.get_module_info("Stage", stage_type) stage = pipeline.add_stage(info, opts) ips = description.get("inputs", {}) for name, desc in ips.items(): load_input(name, desc, index, stage, manifest) return stage
def load_stage(description: Dict, index: Index, pipeline: Pipeline): name = description["name"] opts = description.get("options", {}) info = index.get_module_info("Stage", name) stage = pipeline.add_stage(info, opts) if stage.name == "org.osbuild.rpm": info = index.get_module_info("Input", "org.osbuild.files") ip = stage.add_input("packages", info, "org.osbuild.source") for pkg in stage.options["packages"]: options = None if isinstance(pkg, dict): gpg = pkg.get("check_gpg") if gpg: options = {"metadata": {"rpm.check_gpg": gpg}} pkg = pkg["checksum"] ip.add_reference(pkg, options) elif stage.name == "org.osbuild.ostree": info = index.get_module_info("Input", "org.osbuild.ostree") ip = stage.add_input("commits", info, "org.osbuild.source") commit, ref = opts["commit"], opts.get("ref") options = {"ref": ref} if ref else None ip.add_reference(commit, options)
def load_device(name: str, description: Dict, index: Index, stage: Stage): device_type = description["type"] options = description.get("options", {}) parent = description.get("parent") if parent: device = stage.devices.get(parent) if not parent: raise ValueError(f"Unknown parent device: {parent}") parent = device info = index.get_module_info("Device", device_type) if not info: raise TypeError(f"Missing meta information for {device_type}") stage.add_device(name, info, parent, options)
def load_source(name: str, description: Dict, index: Index, manifest: Manifest): if name == "org.osbuild.files": name = "org.osbuild.curl" info = index.get_module_info("Source", name) if name == "org.osbuild.curl": items = description["urls"] elif name == "org.osbuild.ostree": items = description["commits"] else: raise ValueError(f"Unknown source type: {name}") # NB: the entries, i.e. `urls`, `commits` are left in the # description dict, although the sources are not using # it anymore. The reason is that it makes `describe` work # without any special casing manifest.add_source(info, items, description)
def load(description: Dict, index: Index) -> Manifest: """Load a manifest description""" sources = description.get("sources", {}) pipelines = description.get("pipelines", []) manifest = Manifest() source_refs = set() # load the sources for name, desc in sources.items(): info = index.get_module_info("Source", name) items = desc.get("items", {}) options = desc.get("options", {}) manifest.add_source(info, items, options) source_refs.update(items.keys()) for desc in pipelines: load_pipeline(desc, index, manifest, source_refs) # The "runner" property in the manifest format is the # runner to the run the pipeline with. In osbuild the # "runner" property belongs to the "build" pipeline, # i.e. is what runner to use for it. This we have to # go through the pipelines and fix things up pipelines = manifest.pipelines.values() host_runner = detect_host_runner() runners = { pl.id: pl.runner for pl in pipelines } for pipeline in pipelines: if not pipeline.build: pipeline.runner = host_runner continue runner = runners[pipeline.build] pipeline.runner = runner return manifest
def load_mount(description: Dict, index: Index, stage: Stage): mount_type = description["type"] info = index.get_module_info("Mount", mount_type) name = description["name"] if name in stage.mounts: raise ValueError(f"Duplicated mount '{name}'") source = description.get("source") target = description.get("target") options = description.get("options", {}) device = None if source: device = stage.devices.get(source) if not device: raise ValueError(f"Unknown device '{source}' for mount '{name}'") stage.add_mount(name, info, device, target, options)
def load_stage(description: Dict, index: Index, pipeline: Pipeline, manifest: Manifest, source_refs): stage_type = description["type"] opts = description.get("options", {}) info = index.get_module_info("Stage", stage_type) stage = pipeline.add_stage(info, opts) devs = description.get("devices", {}) devs = sort_devices(devs) for name, desc in devs.items(): load_device(name, desc, index, stage) ips = description.get("inputs", {}) for name, desc in ips.items(): load_input(name, desc, index, stage, manifest, source_refs) mounts = description.get("mounts", []) for mount in mounts: load_mount(mount, index, stage) return stage