Merge branch 'yaml-schemata' into calamares

This commit is contained in:
Adriaan de Groot 2020-06-16 16:07:57 +02:00
commit 066acdbbc6
23 changed files with 436 additions and 0 deletions

116
ci/configvalidator.py Normal file
View File

@ -0,0 +1,116 @@
#! /usr/bin/env python3
#
# SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
# SPDX-License-Identifier: BSD-2-Clause
# License-Filename: LICENSES/BSD2
#
usage = """
Validates a Calamares config file -- YAML syntax -- against a schema.
The schema is also written in YAML syntax, but the schema itself
is JSON-schema. This is possible because all JSON is YAML, and most
YAML is JSON. The limited subset of YAML that Calamares uses is
JSON-representable, anyway.
Usage:
configvalidator.py <schema> <file> ...
"""
# The schemata originally lived outside the Calamares repository,
# without documented tooling. By putting them in the repository
# with the example files and explicit tooling, there's a better
# chance of them catching problems and acting as documentation.
dependencies = """
Dependencies for this tool are: py-yaml and py-jsonschema.
https://pyyaml.org/
https://github.com/Julian/jsonschema
Simple installation is `pip install pyyaml jsonschema`
"""
ERR_IMPORT, ERR_USAGE, ERR_FILE_NOT_FOUND, ERR_SYNTAX, ERR_INVALID = range(1,6)
### DEPENDENCIES
#
#
try:
from jsonschema import validate, SchemaError, ValidationError
from yaml import safe_load, YAMLError
except ImportError as e:
print(e)
print(dependencies)
exit(ERR_IMPORT)
from os.path import exists
import sys
### INPUT VALIDATION
#
#
if len(sys.argv) < 3:
print(usage)
exit(ERR_USAGE)
schema_file_name = sys.argv[1]
config_file_names = sys.argv[2:]
if not exists(schema_file_name):
print(usage)
print("\nSchema file '{}' does not exist.".format(schema_file_name))
exit(ERR_FILE_NOT_FOUND)
for f in config_file_names:
if not exists(f):
print(usage)
print("\nYAML file '{}' does not exist.".format(f))
exit(ERR_FILE_NOT_FOUND)
### FILES SYNTAX CHECK
#
#
with open(schema_file_name, "r") as data:
try:
schema = safe_load(data)
except YAMLError as e:
print("Schema error: {} {}.".format(e.problem, e.problem_mark))
print("\nSchema file '{}' is invalid YAML.".format(schema_file_name))
exit(ERR_SYNTAX)
try:
validate(instance={}, schema=schema)
# While developing the schemata, get full exceptions from schema failure
except SchemaError as e:
print(e)
print("\nSchema file '{}' is invalid JSON-Schema.".format(schema_file_name))
exit(ERR_INVALID)
except ValidationError:
# Just means that empty isn't valid, but the Schema itself is
pass
configs = []
for f in config_file_names:
config = None
with open(f, "r") as data:
try:
config = safe_load(data)
except YAMLError as e:
print("YAML error: {} {}.".format(e.problem, e.problem_mark))
print("\nYAML file '{}' is invalid.".format(f))
exit(ERR_SYNTAX)
if config is None:
print("YAML file '{}' is empty.".format(f))
configs.append(config)
assert len(configs) == len(config_file_names), "Not all configurations loaded."
### SCHEMA VALIDATION
#
#
for c, f in zip(configs, config_file_names):
try:
validate(instance=c, schema=schema)
except ValidationError as e:
print(e)
print("\nConfig file '{}' does not validate in schema.".format(f))
exit(ERR_INVALID)

View File

@ -66,3 +66,21 @@ endforeach()
include( CalamaresAddTranslations )
add_calamares_python_translations( ${CALAMARES_TRANSLATION_LANGUAGES} )
# TODO:3.3: Use FindPython3
if ( BUILD_TESTING AND PYTHONINTERP_FOUND AND PYTHON_EXECUTABLE )
# The tests for each config file are independent of whether the
# module is enabled or not: the config file should match its schema
# regardless.
foreach( SUBDIRECTORY ${SUBDIRECTORIES} )
set( _schema_file "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}/${SUBDIRECTORY}.schema.yaml" )
set( _conf_file "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}/${SUBDIRECTORY}.conf" )
if ( EXISTS "${_schema_file}" AND EXISTS "${_conf_file}" )
add_test(
NAME validate-${SUBDIRECTORY}
COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_SOURCE_DIR}/ci/configvalidator.py" "${_schema_file}" "${_conf_file}"
)
endif()
endforeach()
endif()

View File

@ -0,0 +1,18 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/bootloader
additionalProperties: false
type: object
properties:
efiBootLoader: { type: string, required: true }
kernel: { type: string, required: true }
img: { type: string, required: true }
fallback: { type: str }
timeout: { type: str }
bootloaderEntryName: { type: str }
kernelLine: { type: str }
fallbackKernelLine: { type: str }
grubInstall: { type: string, required: true }
grubMkconfig: { type: string, required: true }
grubCfg: { type: string, required: true }
efiBootloaderId: { type: str }

View File

@ -0,0 +1,16 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/displaymanager
additionalProperties: false
type: object
properties:
"displaymanagers":
type: seq
sequence:
- { type: string, required: true, enum: [slim, sddm, lightdm, gdm, mdm, lxdm, kdm] }
"defaultDesktopEnvironment":
type: map
mapping:
"executable": { type: str }
"desktopFile": { type: str }
"basicSetup": { type: boolean, default: false }

View File

@ -0,0 +1,11 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/finished
additionalProperties: false
type: object
properties:
restartNowEnabled: { type: boolean, default: true } # TODO:3.3: remove
restartNowChecked: { type: boolean, default: false } # TODO:3.3: remove
restartNowCommand: { type: string }
restartNowMode: { type: string, enum: [ never, user-unchecked, user-checked, always ] }
notifyOnFinished: { type: boolean }

View File

@ -0,0 +1,19 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/fstab
additionalProperties: false
type: object
properties:
"mountOptions":
type: map
mapping:
"default": { type: string, required: true }
"btrfs": { type: string, required: true }
"ssdExtraMountOptions":
type: map
mapping:
"ext4": { type: string, required: true }
"jfs": { type: string, required: true }
"xfs": { type: string, required: true }
"swap": { type: string, required: true }
"btrfs": { type: string, required: true }

View File

@ -0,0 +1,15 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/grubcfg
additionalProperties: false
type: object
properties:
"overwrite": { type: boolean, default: false }
"defaults":
type: map
mapping:
"GRUB_TIMEOUT": { type: int, required: true }
"GRUB_DEFAULT": { type: string, required: true }
"GRUB_DISABLE_SUBMENU": { type: boolean, default: true }
"GRUB_TERMINAL_OUTPUT": { type: string, required: true }
"GRUB_DISABLE_RECOVERY": { type: boolean, default: true }

View File

@ -0,0 +1,7 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/initcpio
additionalProperties: false
type: object
properties:
kernel: { type: string, required: true }

View File

@ -0,0 +1,8 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/finished
additionalProperties: keyboard
type: object
properties:
xOrgConfFileName: { type: string, required: true }
convertedKeymapPath: { type: string, required: true }

View File

@ -0,0 +1,17 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/license
additionalProperties: false
type: object
properties:
"entries":
type: seq
sequence:
- type: map
mapping:
"id": { type: str }
"name": { type: str }
"vendor": { type: str }
"type": { type: str }
"url": { type: str }
"required": { type: boolean, default: false }

View File

@ -0,0 +1,10 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/locale
additionalProperties: false
type: object
properties:
"region": { type: str }
"zone": { type: str }
"localeGenPath": { type: string, required: true }
"geoipUrl": { type: str }

View File

@ -0,0 +1,7 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/luksopenswaphookcfg
additionalProperties: false
type: object
properties:
"configFilePath": { type: string, required: true }

View File

@ -0,0 +1,9 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/machineid
additionalProperties: false
type: object
properties:
"systemd": { type: boolean, default: true }
"dbus": { type: boolean, default: true }
"symlink": { type: boolean, default: true }

View File

@ -0,0 +1,24 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/mount
additionalProperties: false
type: object
properties:
"extraMounts":
type: seq
sequence:
- type: map
mapping:
"device": { type: string, required: true }
"fs": { type: str }
"mountPoint": { type: string, required: true }
"options": { type: str }
"extraMountsEfi":
type: seq
sequence:
- type: map
mapping:
"device": { type: string, required: true }
"fs": { type: str }
"mountPoint": { type: string, required: true }
"options": { type: str }

View File

@ -0,0 +1,7 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/netinstall
additionalProperties: false
type: object
properties:
groupsUrl: { type: string, required: true }

View File

@ -0,0 +1,33 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/packages
additionalProperties: false
type: object
properties:
"backend": { type: string, required: true, enum: [packagekit, zypp, yum, dnf, urpmi, apt, pacman, portage, entropy] }
"update_db": { type: boolean, default: true }
"operations":
type: seq
sequence:
- type: map
mapping:
"install":
type: seq
sequence:
- { type: text }
"remove":
type: seq
sequence:
- { type: text }
"localInstall":
type: seq
sequence:
- { type: text }
"try_install":
type: seq
sequence:
- { type: text }
"try_remove":
type: seq
sequence:
- { type: text }

View File

@ -0,0 +1,11 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/partition
additionalProperties: false
type: object
properties:
efiSystemPartition: { type: string, required: true }
ensureSuspendToDisk: { type: boolean, default: true }
drawNestedPartitions: { type: boolean, default: false }
alwaysShowPartitionLabels: { type: boolean, default: true }
defaultFileSystemType: { type: string, required: true }

View File

@ -0,0 +1,7 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/plymouthcfg
additionalProperties: false
type: object
properties:
plymouth_theme: { type: str }

View File

@ -0,0 +1,7 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/removeuser
additionalProperties: false
type: object
properties:
"username": { type: string, required: true }

View File

@ -0,0 +1,8 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/umount
additionalProperties: false
type: object
properties:
"srcLog": { type: str }
"destLog": { type: str }

View File

@ -0,0 +1,14 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/unpackfs
additionalProperties: false
type: object
properties:
"unpack":
type: seq
sequence:
- type: map
mapping:
"source": { type: string, required: true }
"sourcefs": { type: str }
"destination": { type: str }

View File

@ -0,0 +1,18 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/users
additionalProperties: false
type: object
properties:
"defaultGroups":
required: true
type: seq
sequence:
- { type: str }
"autologinGroup": { type: string, required: true }
"doAutologin": { type: boolean, default: true }
"sudoersGroup": { type: string, required: true }
"setRootPassword": { type: boolean, default: true }
"availableShells": { type: str }
"avatarFilePath": { type: str }
"doReusePassword": { type: boolean, default: true }

View File

@ -0,0 +1,36 @@
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/welcome
additionalProperties: false
type: object
properties:
# TODO:3.3: drop the string alternatives and put the URL part in Branding
showSupportUrl: { anyOf: [ { type: boolean, default: true }, { type: string } ] }
showKnownIssuesUrl: { anyOf: [ { type: boolean, default: true }, { type: string } ] }
showReleaseNotesUrl: { anyOf: [ { type: boolean, default: true }, { type: string } ] }
showDonateUrl: { anyOf: [ { type: boolean, default: true }, { type: string } ] }
requirements:
additionalProperties: false
type: object
properties:
requiredStorage: { type: number }
requiredRam: { type: number }
internetCheckUrl: { type: string }
check:
type: array
items: { type: string, enum: [storage, ram, power, internet, root, screen], unique: true }
required: # Key-name in the config-file
type: array
items: { type: string, enum: [storage, ram, power, internet, root, screen], unique: true }
required: [ requiredStorage, requiredRam, check ] # Schema keyword
# TODO: refactor, this is reused in locale
geoip:
additionalProperties: false
type: object
properties:
style: { type: string, enum: [ none, fixed, xml, json ] }
url: { type: string }
selector: { type: string }
required: [ style, url, selector ]