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 validate(manifest: Dict, index: Index) -> ValidationResult: schema = index.get_schema("Manifest", version="2") result = schema.validate(manifest) def validate_input(ip, path): name = ip["type"] schema = index.get_schema("Input", name, version="2") res = schema.validate(ip) result.merge(res, path=path) def validate_stage(stage, path): name = stage["type"] schema = index.get_schema("Stage", name, version="2") res = schema.validate(stage) result.merge(res, path=path) inputs = stage.get("inputs", {}) for name, ip in inputs.items(): validate_input(ip, path + ["inputs", name]) def validate_pipeline(pipeline, path): stages = pipeline.get("stages", []) for i, stage in enumerate(stages): validate_stage(stage, path + ["stages", i]) # sources sources = manifest.get("sources", {}) for name, source in sources.items(): schema = index.get_schema("Source", name, version="2") res = schema.validate(source) result.merge(res, path=["sources", name]) # pipelines pipelines = manifest.get("pipelines", []) for i, pipeline in enumerate(pipelines): validate_pipeline(pipeline, path=["pipelines", i]) return result
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_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)