formats/v2: mounts are arrays

The order of entries in a dictionary is not specified by the JSON
standard and hard to control when marshalling dictionaries in Go.
Since the order of mounts is important and the wrong order leads
to wrong mount trees change the `mounts` field to an array. This
breaks existing manifests but after careful deliberation it was
concluded that the original schema with mounts as dictionaries
is not something we want to support. Apologies to everyone.

Adjust the schema of the copy and zipl stage accordingly.
This commit is contained in:
Christian Kellner 2021-07-20 17:34:04 +00:00
parent 50627b713c
commit ae1296e33a
8 changed files with 57 additions and 45 deletions

View file

@ -75,6 +75,7 @@ def describe(manifest: Manifest, *, with_id=False) -> Dict:
def describe_mount(mnt):
desc = {
"name": mnt.name,
"type": mnt.info.name,
"device": mnt.device.name,
"target": mnt.target
@ -85,10 +86,10 @@ def describe(manifest: Manifest, *, with_id=False) -> Dict:
return desc
def describe_mounts(mounts: Dict):
desc = {
name: describe_mount(mnt)
for name, mnt in mounts.items()
}
desc = [
describe_mount(mnt)
for mnt in mounts.values()
]
return desc
def describe_stage(s: Stage):
@ -214,10 +215,15 @@ def load_input(name: str, description: Dict, index: Index, stage: Stage, manifes
ip.add_reference(r, desc)
def load_mount(name: str, description: Dict, index: Index, stage: Stage):
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["source"]
target = description["target"]
@ -245,9 +251,9 @@ def load_stage(description: Dict, index: Index, pipeline: Pipeline, manifest: Ma
for name, desc in ips.items():
load_input(name, desc, index, stage, manifest, source_refs)
mounts = description.get("mounts", {})
for name, desc in mounts.items():
load_mount(name, desc, index, stage)
mounts = description.get("mounts", [])
for mount in mounts:
load_mount(mount, index, stage)
return stage
@ -394,6 +400,10 @@ def validate(manifest: Dict, index: Index) -> ValidationResult:
def validate_stage_modules(klass, stage, path):
group = ModuleInfo.MODULES[klass]
items = stage.get(group, {})
if isinstance(items, list):
items = {i["name"]: i for i in items}
for name, mod in items.items():
validate_module(mod, klass, path + [group, name])

View file

@ -63,16 +63,16 @@
"mounts": {
"title": "Collection of mount points for a stage",
"additionalProperties": {
"$ref": "#/definitions/mount"
}
"type": "array",
"items": { "$ref": "#/definitions/mount"}
},
"mount": {
"title": "Mount point for a stage",
"additionalProperties": false,
"required": ["type", "source", "target"],
"required": ["name", "type", "source", "target"],
"properties": {
"name": { "type": "string" },
"type": { "type": "string" },
"source": {
"type": "string"

View file

@ -64,8 +64,7 @@ SCHEMA_2 = r"""
"additionalProperties": true
},
"mounts": {
"type": "object",
"additionalProperties": true
"type": "array"
},
"inputs": {
"type": "object",

View file

@ -47,15 +47,8 @@ SCHEMA_2 = r"""
}
},
"mounts": {
"type": "object",
"additionalProperties": true,
"required": ["root"],
"properties": {
"root": {
"type": "object",
"additionalProperties": true
}
}
"type": "array",
"minItems": 1
}
"""

View file

@ -1763,13 +1763,14 @@
}
}
},
"mounts": {
"root": {
"mounts": [
{
"name": "root",
"type": "org.osbuild.ext4",
"source": "root",
"target": "/"
}
}
]
}
]
},
@ -1935,13 +1936,14 @@
}
}
},
"mounts": {
"efi": {
"mounts": [
{
"name": "efi",
"type": "org.osbuild.fat",
"source": "efi",
"target": "/"
}
}
]
},
{
"type": "org.osbuild.copy",

View file

@ -534,13 +534,14 @@
}
}
},
"mounts": {
"root": {
"mounts": [
{
"name": "root",
"type": "org.osbuild.ext4",
"source": "root",
"target": "/"
}
}
]
}
]
},
@ -720,13 +721,14 @@
}
}
},
"mounts": {
"efi": {
"mounts": [
{
"name": "efi",
"type": "org.osbuild.fat",
"source": "efi",
"target": "/"
}
}
]
},
{
"type": "org.osbuild.copy",

View file

@ -1080,23 +1080,26 @@
}
}
},
"mounts": {
"root": {
"mounts": [
{
"name": "root",
"type": "org.osbuild.xfs",
"source": "root",
"target": "/"
},
"boot": {
{
"name": "boot",
"type": "org.osbuild.ext4",
"source": "boot",
"target": "/boot"
},
"efi": {
{
"name": "efi",
"type": "org.osbuild.fat",
"source": "efi",
"target": "/boot/efi"
}
}
]
},
{
"type": "org.osbuild.grub2.inst",

View file

@ -534,23 +534,26 @@
}
}
},
"mounts": {
"root": {
"mounts": [
{
"name": "root",
"type": "org.osbuild.xfs",
"source": "root",
"target": "/"
},
"boot": {
{
"name": "boot",
"type": "org.osbuild.ext4",
"source": "boot",
"target": "/boot"
},
"efi": {
{
"name": "efi",
"type": "org.osbuild.fat",
"source": "efi",
"target": "/boot/efi"
}
}
]
},
{
"type": "org.osbuild.grub2.inst",