diff --git a/stages/org.osbuild.anaconda b/stages/org.osbuild.anaconda index f4bdf3bc..b3f8852a 100755 --- a/stages/org.osbuild.anaconda +++ b/stages/org.osbuild.anaconda @@ -1,56 +1,9 @@ #!/usr/bin/python3 -""" -Configure basic aspects of the anaconda installer - -Create an anaconda configuration file `90-osbuild.conf` in -the folder `/etc/anaconda/conf.d` to configure anaconda. - -Currently only the list of enabled kickstart modules is -configurable via the `kickstart-modules` option. -""" - import os import sys import osbuild.api -SCHEMA = """ -"additionalProperties": true, -"properties": { - "kickstart-modules": { - "type": "array", - "description": "Kick start modules to enable", - "items": { - "type": "string" - }, - "minItems": 1 - }, - "activatable-modules": { - "type": "array", - "description": "Kick start modules to activate", - "items": { - "type": "string" - }, - "minItems": 1 - }, - "forbidden-modules": { - "type": "array", - "description": "Kick start modules to forbid", - "items": { - "type": "string" - }, - "minItems": 1 - }, - "optional-modules": { - "type": "array", - "description": "Kick start modules to activate but are allowed to fail", - "items": { - "type": "string" - }, - "minItems": 1 - } -} -""" CONFIG = """ # osbuild customizations diff --git a/stages/org.osbuild.anaconda.meta.json b/stages/org.osbuild.anaconda.meta.json new file mode 100644 index 00000000..1fec3e78 --- /dev/null +++ b/stages/org.osbuild.anaconda.meta.json @@ -0,0 +1,46 @@ +{ + "summary": "Configure basic aspects of the anaconda installer", + "description": [ + "Create an anaconda configuration file `90-osbuild.conf` in", + "the folder `/etc/anaconda/conf.d` to configure anaconda.", + "Currently only the list of enabled kickstart modules is", + "configurable via the `kickstart-modules` option." + ], + "schema": { + "additionalProperties": true, + "properties": { + "kickstart-modules": { + "type": "array", + "description": "Kick start modules to enable", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "activatable-modules": { + "type": "array", + "description": "Kick start modules to activate", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "forbidden-modules": { + "type": "array", + "description": "Kick start modules to forbid", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "optional-modules": { + "type": "array", + "description": "Kick start modules to activate but are allowed to fail", + "items": { + "type": "string" + }, + "minItems": 1 + } + } + } +} diff --git a/stages/org.osbuild.authconfig b/stages/org.osbuild.authconfig index b56ff7cb..f26fae40 100755 --- a/stages/org.osbuild.authconfig +++ b/stages/org.osbuild.authconfig @@ -1,26 +1,10 @@ #!/usr/bin/python3 -""" -Configure authentication sources using authconfig. - -Applies the default settings. Backups are cleared. - -Notes: - - Requires 'chroot' in the buildroot. - - Runs the 'authconfig' binary from the image in the chroot. -""" - - import shutil import subprocess import sys import osbuild.api -SCHEMA = """ -"additionalProperties": false, -"description": "Configure authentication sources." -""" - def main(tree): cmd = [ diff --git a/stages/org.osbuild.authconfig.meta.json b/stages/org.osbuild.authconfig.meta.json new file mode 100644 index 00000000..e5d0e730 --- /dev/null +++ b/stages/org.osbuild.authconfig.meta.json @@ -0,0 +1,13 @@ +{ + "summary": "Configure authentication sources using authconfig.", + "description": [ + "Applies the default settings. Backups are cleared.", + "Notes:", + " - Requires 'chroot' in the buildroot.", + " - Runs the 'authconfig' binary from the image in the chroot." + ], + "schema": { + "additionalProperties": false, + "description": "Configure authentication sources." + } +} diff --git a/stages/org.osbuild.authselect b/stages/org.osbuild.authselect index 5724dfb8..1de1af66 100755 --- a/stages/org.osbuild.authselect +++ b/stages/org.osbuild.authselect @@ -1,45 +1,9 @@ #!/usr/bin/python3 -""" -Select system identity and authentication sources with authselect. - -Sets system identity and authentication sources. - -The stage calls `authselect select` to set authselect profile to 'profile'. -Optionally a list of profile features to enable may be provided using 'features' -option. The list of available profile features can be obtained by running -`authselect list-features `. - -Notes: - - Requires 'chroot' in the buildroot. - - Runs the 'authselect' binary from the image in the chroot. -""" - - import subprocess import sys import osbuild.api -SCHEMA = """ -"additionalProperties": false, -"required": ["profile"], -"description": "Select system identity and authentication sources.", -"properties": { - "profile": { - "type": "string", - "description": "Desired authselect profile to activate." - }, - "features": { - "type": "array", - "description": "Features of the selected profile to activate.", - "minItems": 1, - "items": { - "type": "string" - } - } -} -""" - def main(tree, options): profile = options["profile"] diff --git a/stages/org.osbuild.authselect.meta.json b/stages/org.osbuild.authselect.meta.json new file mode 100644 index 00000000..9f3a9c5b --- /dev/null +++ b/stages/org.osbuild.authselect.meta.json @@ -0,0 +1,34 @@ +{ + "summary": "Select system identity and authentication sources with authselect.", + "description": [ + "Sets system identity and authentication sources.", + "The stage calls `authselect select` to set authselect profile to 'profile'.", + "Optionally a list of profile features to enable may be provided using 'features'", + "option. The list of available profile features can be obtained by running", + "`authselect list-features `.", + "Notes:", + " - Requires 'chroot' in the buildroot.", + " - Runs the 'authselect' binary from the image in the chroot." + ], + "schema": { + "additionalProperties": false, + "required": [ + "profile" + ], + "description": "Select system identity and authentication sources.", + "properties": { + "profile": { + "type": "string", + "description": "Desired authselect profile to activate." + }, + "features": { + "type": "array", + "description": "Features of the selected profile to activate.", + "minItems": 1, + "items": { + "type": "string" + } + } + } + } +} diff --git a/stages/org.osbuild.bootc.install-to-filesystem b/stages/org.osbuild.bootc.install-to-filesystem index a299f1af..530ac666 100755 --- a/stages/org.osbuild.bootc.install-to-filesystem +++ b/stages/org.osbuild.bootc.install-to-filesystem @@ -1,15 +1,4 @@ #!/usr/bin/python3 -""" -Run bootc install to-filesystem - -Note that this needs the disk.img in the inputs as one continous -devices so that bootupd can install grub to the mbr. It also needs -all relevant mount points for booting (e.g. /boot, /boot/efi) in -mounted in the "mounts" path. - -Buildhost commands used: bootc -""" - import subprocess import sys import tempfile @@ -17,48 +6,6 @@ import tempfile import osbuild.api from osbuild.util import containers -CAPABILITIES = ["CAP_MAC_ADMIN"] - -SCHEMA_2 = r""" -"inputs": { - "type": "object", - "additionalProperties": false, - "required": ["images"], - "properties": { - "images": { - "type": "object", - "additionalProperties": true - } - } -}, -"options": { - "additionalProperties": false, - "properties": { - "root-ssh-authorized-keys": { - "description": "array of SSH Public Keys to add to roots authorized_keys", - "type": "array", - "items": { - "type": "string" - } - }, - "kernel-args": { - "description": "array of additional kernel arguments", - "type": "array", - "items": { - "type": "string" - } - } - } -}, -"devices": { - "type": "object", - "additionalProperties": true -}, -"mounts": { - "type": "array" -} -""" - def main(options, inputs, paths): images = containers.parse_containers_input(inputs) diff --git a/stages/org.osbuild.bootc.install-to-filesystem.meta.json b/stages/org.osbuild.bootc.install-to-filesystem.meta.json new file mode 100644 index 00000000..80cc721e --- /dev/null +++ b/stages/org.osbuild.bootc.install-to-filesystem.meta.json @@ -0,0 +1,54 @@ +{ + "summary": "Run bootc install to-filesystem", + "description": [ + "Note that this needs the disk.img in the inputs as one continous", + "devices so that bootupd can install grub to the mbr. It also needs", + "all relevant mount points for booting (e.g. /boot, /boot/efi) in", + "mounted in the \"mounts\" path.", + "Buildhost commands used: bootc" + ], + "capabilities": [ + "CAP_MAC_ADMIN" + ], + "schema_2": { + "inputs": { + "type": "object", + "additionalProperties": false, + "required": [ + "images" + ], + "properties": { + "images": { + "type": "object", + "additionalProperties": true + } + } + }, + "options": { + "additionalProperties": false, + "properties": { + "root-ssh-authorized-keys": { + "description": "array of SSH Public Keys to add to roots authorized_keys", + "type": "array", + "items": { + "type": "string" + } + }, + "kernel-args": { + "description": "array of additional kernel arguments", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "devices": { + "type": "object", + "additionalProperties": true + }, + "mounts": { + "type": "array" + } + } +} diff --git a/stages/org.osbuild.bootiso.mono b/stages/org.osbuild.bootiso.mono index 52e6d626..41c5efe6 100755 --- a/stages/org.osbuild.bootiso.mono +++ b/stages/org.osbuild.bootiso.mono @@ -1,28 +1,4 @@ #!/usr/bin/python3 -""" -Assemble a file system tree for a bootable iso - -This stage prepares a file system tree for a bootable ISO, like the -Anaconda installer. It follows the convention used by Lorax to -create the boot isos: It takes an input `rootfs`, which will serve -as the root file system. This is copied into a file with a `ext4` -file system which in turn will be made into a squashfs file system. -Options for controlling the root file-system creation can be given -via `rootfs`, like it size and the compression to be used. - -The boot loader is configured via the `isolinux` and `efi` options. -Which combination makes sense depends on the targeted platform and -architecture. -The kernel and initrd are taken from the tree given via the `kernel` -input, or if that was not specified, from `rootfs`. In either case -it will look for the specified kernel in the `/boot` directory. -Additionally kernel command line flags can passed via `kernel_opts`. - -This stage has the `.mono` suffix to indicate that is a monolithic -stage that could, and in the future will be, broken up into smaller -pieces. -""" - import contextlib import os import re @@ -34,119 +10,6 @@ import tempfile import osbuild.api import osbuild.remoteloop as remoteloop -SCHEMA_2 = """ -"options": { - "additionalProperties": false, - "required": ["product", "kernel", "isolabel"], - "properties": { - "product": { - "type": "object", - "additionalProperties": false, - "required": ["name", "version"], - "properties": { - "name": {"type": "string"}, - "version": {"type": "string"} - } - }, - "kernel": { - "type": "string" - }, - "isolabel": { - "type": "string" - }, - "efi": { - "type": "object", - "additionalProperties": false, - "required": ["architectures", "vendor"], - "properties": { - "architectures": { - "type": "array", - "items": { - "type": "string" - } - }, - "vendor": { - "type": "string" - } - } - }, - "isolinux": { - "type": "object", - "additionalProperties": false, - "required": ["enabled"], - "properties": { - "enabled": { - "type": "boolean" - }, - "debug": { - "type": "boolean" - } - } - }, - "kernel_opts": { - "description": "Additional kernel boot options", - "type": "string" - }, - "templates": { - "type": "string", - "default": "99-generic" - }, - "rootfs": { - "type": "object", - "additionalProperties": false, - "properties": { - "compression": { - "type": "object", - "additionalProperties": false, - "required": ["method"], - "properties": { - "method": { - "enum": ["gzip", "xz", "lz4"] - }, - "options": { - "type": "object", - "additionalProperties": false, - "properties": { - "bcj": { - "enum": [ - "x86", - "arm", - "armthumb", - "powerpc", - "sparc", - "ia64" - ] - } - } - } - } - }, - "size": { - "type": "integer", - "description": "size in MB", - "default": 3072 - } - } - } - } -}, -"inputs": { - "type": "object", - "additionalProperties": false, - "required": ["rootfs"], - "properties": { - "rootfs": { - "type": "object", - "additionalProperties": true - }, - "kernel": { - "type": "object", - "additionalProperties": true - } - } -} -""" - LORAX_TEMPLATES = "/usr/share/lorax/templates.d" diff --git a/stages/org.osbuild.bootiso.mono.meta.json b/stages/org.osbuild.bootiso.mono.meta.json new file mode 100644 index 00000000..06bc0ee0 --- /dev/null +++ b/stages/org.osbuild.bootiso.mono.meta.json @@ -0,0 +1,158 @@ +{ + "summary": "Assemble a file system tree for a bootable iso", + "description": [ + "This stage prepares a file system tree for a bootable ISO, like the", + "Anaconda installer. It follows the convention used by Lorax to", + "create the boot isos: It takes an input `rootfs`, which will serve", + "as the root file system. This is copied into a file with a `ext4`", + "file system which in turn will be made into a squashfs file system.", + "Options for controlling the root file-system creation can be given", + "via `rootfs`, like it size and the compression to be used.", + "The boot loader is configured via the `isolinux` and `efi` options.", + "Which combination makes sense depends on the targeted platform and", + "architecture.", + "The kernel and initrd are taken from the tree given via the `kernel`", + "input, or if that was not specified, from `rootfs`. In either case", + "it will look for the specified kernel in the `/boot` directory.", + "Additionally kernel command line flags can passed via `kernel_opts`.", + "This stage has the `.mono` suffix to indicate that is a monolithic", + "stage that could, and in the future will be, broken up into smaller", + "pieces." + ], + "schema_2": { + "options": { + "additionalProperties": false, + "required": [ + "product", + "kernel", + "isolabel" + ], + "properties": { + "product": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "version" + ], + "properties": { + "name": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "kernel": { + "type": "string" + }, + "isolabel": { + "type": "string" + }, + "efi": { + "type": "object", + "additionalProperties": false, + "required": [ + "architectures", + "vendor" + ], + "properties": { + "architectures": { + "type": "array", + "items": { + "type": "string" + } + }, + "vendor": { + "type": "string" + } + } + }, + "isolinux": { + "type": "object", + "additionalProperties": false, + "required": [ + "enabled" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "debug": { + "type": "boolean" + } + } + }, + "kernel_opts": { + "description": "Additional kernel boot options", + "type": "string" + }, + "templates": { + "type": "string", + "default": "99-generic" + }, + "rootfs": { + "type": "object", + "additionalProperties": false, + "properties": { + "compression": { + "type": "object", + "additionalProperties": false, + "required": [ + "method" + ], + "properties": { + "method": { + "enum": [ + "gzip", + "xz", + "lz4" + ] + }, + "options": { + "type": "object", + "additionalProperties": false, + "properties": { + "bcj": { + "enum": [ + "x86", + "arm", + "armthumb", + "powerpc", + "sparc", + "ia64" + ] + } + } + } + } + }, + "size": { + "type": "integer", + "description": "size in MB", + "default": 3072 + } + } + } + } + }, + "inputs": { + "type": "object", + "additionalProperties": false, + "required": [ + "rootfs" + ], + "properties": { + "rootfs": { + "type": "object", + "additionalProperties": true + }, + "kernel": { + "type": "object", + "additionalProperties": true + } + } + } + } +} diff --git a/stages/org.osbuild.bootupd b/stages/org.osbuild.bootupd index 5663ea3e..be11fb29 100755 --- a/stages/org.osbuild.bootupd +++ b/stages/org.osbuild.bootupd @@ -1,14 +1,4 @@ #!/usr/bin/python3 -""" -Install GRUB on both BIOS and UEFI systems, -ensuring that your bootloader stays up-to-date. - -Bootupd supports updating GRUB and shim for -UEFI firmware on x86_64 and aarch64, -and GRUB for BIOS firmware on x86_64. -The project is deployed in Fedora CoreOS and derivatives -""" - import contextlib import json import os @@ -18,84 +8,6 @@ import sys import osbuild.api from osbuild.util import ostree -SCHEMA_2 = r""" -"devices": { - "type": "object", - "additionalProperties": true -}, -"mounts": { - "type": "array" -}, -"options": { - "additionalProperties": false, - "properties": { - "deployment": { - "type": "object", - "additionalProperties": false, - "oneOf": [ - { - "properties": { - "default": {"enum": [false]} - }, - "required": ["osname", "ref"] - }, - { - "properties": { - "default": {"enum": [true]} - }, - "not": { - "anyOf": [ - {"required": ["osname"]}, - {"required": ["ref"]}, - {"required": ["serial"]} - ] - } - } - ], - "properties": { - "osname": { - "description": "Name of the stateroot to be used in the deployment", - "type": "string" - }, - "ref": { - "description": "OStree ref to create and use for deployment", - "type": "string" - }, - "serial": { - "description": "The deployment serial (usually '0')", - "type": "number", - "default": 0 - }, - "default": { - "description": "Find and use the default ostree deployment", - "type": "boolean", - "default": false - } - } - }, - "static-configs": { - "description": "Install the grub configs defined for Fedora CoreOS", - "type": "boolean" - }, - "bios": { - "additionalProperties": false, - "type": "object", - "required": ["device"], - "properties": { - "device": { - "description": "Name of stage device to install GRUB for BIOS-based systems.", - "type": "string" - }, - "partition": { - "description": "The partition on the stage device to install to, if installing to a partition", - "type": "number" - } - } - } - } -} -""" - @contextlib.contextmanager def bind_mounts(sources, dest_root): diff --git a/stages/org.osbuild.bootupd.gen-metadata b/stages/org.osbuild.bootupd.gen-metadata index fe4072ec..b6f10b9f 100755 --- a/stages/org.osbuild.bootupd.gen-metadata +++ b/stages/org.osbuild.bootupd.gen-metadata @@ -1,15 +1,4 @@ #!/usr/bin/python3 -""" -Transforms /usr/lib/ostree-boot into a bootupd-compatible update payload. - -Scrapes metadata (e.g. RPM versions) about shim/grub and puts them along with their component files in -`/usr/lib/bootupd/updates/`. - -Notes: - - Requires 'chroot' in the buildroot. - - Runs the 'bootupctl' binary from the image in the chroot. -""" - import os import subprocess import sys @@ -17,12 +6,6 @@ import sys import osbuild.api from osbuild.util.mnt import MountGuard, MountPermissions -SCHEMA_2 = r""" -"options": { - "additionalProperties": false -} -""" - def main(tree): with MountGuard() as mounter: diff --git a/stages/org.osbuild.bootupd.gen-metadata.meta.json b/stages/org.osbuild.bootupd.gen-metadata.meta.json new file mode 100644 index 00000000..df26c252 --- /dev/null +++ b/stages/org.osbuild.bootupd.gen-metadata.meta.json @@ -0,0 +1,15 @@ +{ + "summary": "Transforms /usr/lib/ostree-boot into a bootupd-compatible update payload.", + "description": [ + "Scrapes metadata (e.g. RPM versions) about shim/grub and puts them along with their component files in", + "`/usr/lib/bootupd/updates/`.", + "Notes:", + " - Requires 'chroot' in the buildroot.", + " - Runs the 'bootupctl' binary from the image in the chroot." + ], + "schema_2": { + "options": { + "additionalProperties": false + } + } +} diff --git a/stages/org.osbuild.bootupd.meta.json b/stages/org.osbuild.bootupd.meta.json new file mode 100644 index 00000000..7cf8f9f5 --- /dev/null +++ b/stages/org.osbuild.bootupd.meta.json @@ -0,0 +1,111 @@ +{ + "summary": "Install GRUB on both BIOS and UEFI systems,\nensuring that your bootloader stays up-to-date.", + "description": [ + "Bootupd supports updating GRUB and shim for", + "UEFI firmware on x86_64 and aarch64,", + "and GRUB for BIOS firmware on x86_64.", + "The project is deployed in Fedora CoreOS and derivatives" + ], + "schema_2": { + "devices": { + "type": "object", + "additionalProperties": true + }, + "mounts": { + "type": "array" + }, + "options": { + "additionalProperties": false, + "properties": { + "deployment": { + "type": "object", + "additionalProperties": false, + "oneOf": [ + { + "properties": { + "default": { + "enum": [ + false + ] + } + }, + "required": [ + "osname", + "ref" + ] + }, + { + "properties": { + "default": { + "enum": [ + true + ] + } + }, + "not": { + "anyOf": [ + { + "required": [ + "osname" + ] + }, + { + "required": [ + "ref" + ] + }, + { + "required": [ + "serial" + ] + } + ] + } + } + ], + "properties": { + "osname": { + "description": "Name of the stateroot to be used in the deployment", + "type": "string" + }, + "ref": { + "description": "OStree ref to create and use for deployment", + "type": "string" + }, + "serial": { + "description": "The deployment serial (usually '0')", + "type": "number", + "default": 0 + }, + "default": { + "description": "Find and use the default ostree deployment", + "type": "boolean", + "default": false + } + } + }, + "static-configs": { + "description": "Install the grub configs defined for Fedora CoreOS", + "type": "boolean" + }, + "bios": { + "additionalProperties": false, + "type": "object", + "required": [ + "device" + ], + "properties": { + "device": { + "description": "Name of stage device to install GRUB for BIOS-based systems.", + "type": "string" + }, + "partition": { + "description": "The partition on the stage device to install to, if installing to a partition", + "type": "number" + } + } + } + } + } + } +} diff --git a/stages/org.osbuild.btrfs.subvol b/stages/org.osbuild.btrfs.subvol index 742b13d9..20bb61b7 100755 --- a/stages/org.osbuild.btrfs.subvol +++ b/stages/org.osbuild.btrfs.subvol @@ -1,46 +1,10 @@ #!/usr/bin/python3 -""" -Create subvolumes on a mounted btrfs partition. - -See `btrfs`(8). - -Buildhost commands used: `btrfs`. -""" - import os import subprocess import sys import osbuild.api -SCHEMA_2 = r""" -"options": { - "additionalProperties": false, - "properties": { - "subvolumes": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "required": ["name"], - "properties": { - "name": { - "type": "string" - } - } - } - } - } -}, -"devices": { - "type": "object", - "additionalProperties": true -}, -"mounts": { - "type": "array" -} -""" - def main(paths, options): volume = paths["mounts"] diff --git a/stages/org.osbuild.btrfs.subvol.meta.json b/stages/org.osbuild.btrfs.subvol.meta.json new file mode 100644 index 00000000..4e631e88 --- /dev/null +++ b/stages/org.osbuild.btrfs.subvol.meta.json @@ -0,0 +1,36 @@ +{ + "summary": "Create subvolumes on a mounted btrfs partition.", + "description": [ + "See `btrfs`(8).", + "Buildhost commands used: `btrfs`." + ], + "schema_2": { + "options": { + "additionalProperties": false, + "properties": { + "subvolumes": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + } + } + } + } + } + }, + "devices": { + "type": "object", + "additionalProperties": true + }, + "mounts": { + "type": "array" + } + } +} diff --git a/stages/org.osbuild.buildstamp b/stages/org.osbuild.buildstamp index ae5c5bac..01917e9b 100755 --- a/stages/org.osbuild.buildstamp +++ b/stages/org.osbuild.buildstamp @@ -1,47 +1,10 @@ #!/usr/bin/python3 -""" -Create a /.buildstamp file describing the system - -This will create a './buildstamp' with the specified parameters. -""" - import configparser import datetime import sys import osbuild.api -SCHEMA = """ -"additionalProperties": true, -"required": ["arch", "product", "version", "final"], -"properties": { - "arch": { - "description": "Build architecture.", - "type": "string" - }, - "product": { - "description": "The product name.", - "type": "string" - }, - "version": { - "description": "The version .", - "type": "string" - }, - "final": { - "description": "The product.", - "type": "boolean" - }, - "variant": { - "description": "The variant of the product.", - "type": "string" - }, - "bugurl": { - "description": "The bugurl of the product.", - "type": "string" - } -} -""" - def main(tree, options): buildarch = options["arch"] diff --git a/stages/org.osbuild.buildstamp.meta.json b/stages/org.osbuild.buildstamp.meta.json new file mode 100644 index 00000000..c9bf8b58 --- /dev/null +++ b/stages/org.osbuild.buildstamp.meta.json @@ -0,0 +1,41 @@ +{ + "summary": "Create a /.buildstamp file describing the system", + "description": [ + "This will create a './buildstamp' with the specified parameters." + ], + "schema": { + "additionalProperties": true, + "required": [ + "arch", + "product", + "version", + "final" + ], + "properties": { + "arch": { + "description": "Build architecture.", + "type": "string" + }, + "product": { + "description": "The product name.", + "type": "string" + }, + "version": { + "description": "The version .", + "type": "string" + }, + "final": { + "description": "The product.", + "type": "boolean" + }, + "variant": { + "description": "The variant of the product.", + "type": "string" + }, + "bugurl": { + "description": "The bugurl of the product.", + "type": "string" + } + } + } +} diff --git a/stages/org.osbuild.chattr b/stages/org.osbuild.chattr index 0bc8aa0e..b1e6ad88 100755 --- a/stages/org.osbuild.chattr +++ b/stages/org.osbuild.chattr @@ -1,8 +1,4 @@ #!/usr/bin/python3 -""" -Runs `chattr` to set file/directory attributes. -""" - import os import subprocess import sys @@ -11,38 +7,6 @@ from urllib.parse import ParseResult, urlparse import osbuild.api -SCHEMA_2 = r""" -"options": { - "additionalProperties": false, - "properties": { - "items": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^mount:\/\/[^\/]+\/|^tree:\/\/\/": { - "type": "object", - "required": ["immutable"], - "properties": { - "immutable": { - "type": "boolean", - "description": "Make the file/directory immutable", - "default": true - } - } - } - } - } - } -}, -"devices": { - "type": "object", - "additionalProperties": true -}, -"mounts": { - "type": "array" -} -""" - def parse_mount(url: ParseResult, args: Dict): name = url.netloc diff --git a/stages/org.osbuild.chattr.meta.json b/stages/org.osbuild.chattr.meta.json new file mode 100644 index 00000000..9710885a --- /dev/null +++ b/stages/org.osbuild.chattr.meta.json @@ -0,0 +1,37 @@ +{ + "summary": "Runs `chattr` to set file/directory attributes.", + "description": [], + "schema_2": { + "options": { + "additionalProperties": false, + "properties": { + "items": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^mount://[^/]+/|^tree:///": { + "type": "object", + "required": [ + "immutable" + ], + "properties": { + "immutable": { + "type": "boolean", + "description": "Make the file/directory immutable", + "default": true + } + } + } + } + } + } + }, + "devices": { + "type": "object", + "additionalProperties": true + }, + "mounts": { + "type": "array" + } + } +} diff --git a/stages/org.osbuild.chmod b/stages/org.osbuild.chmod index 0453679d..e41abedf 100755 --- a/stages/org.osbuild.chmod +++ b/stages/org.osbuild.chmod @@ -1,10 +1,4 @@ #!/usr/bin/python3 -""" -Change file mode bits - -Change the file mode bits of one or more files or directories inside the tree. -""" - import os import subprocess import sys @@ -12,35 +6,6 @@ import sys import osbuild.api from osbuild.util.path import in_tree -SCHEMA_2 = r""" -"options": { - "additionalProperties": false, - "properties": { - "items": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^\\/(?!\\.\\.)((?!\\/\\.\\.\\/).)+$": { - "type": "object", - "required": ["mode"], - "properties": { - "mode": { - "type": "string", - "description": "Symbolic or numeric octal mode" - }, - "recursive": { - "type": "boolean", - "description": "Change modes recursively", - "default": false - } - } - } - } - } - } -} -""" - def chmod(path: str, mode: str, recursive: bool): arguments = [mode] diff --git a/stages/org.osbuild.chmod.meta.json b/stages/org.osbuild.chmod.meta.json new file mode 100644 index 00000000..2f5eb9de --- /dev/null +++ b/stages/org.osbuild.chmod.meta.json @@ -0,0 +1,36 @@ +{ + "summary": "Change file mode bits", + "description": [ + "Change the file mode bits of one or more files or directories inside the tree." + ], + "schema_2": { + "options": { + "additionalProperties": false, + "properties": { + "items": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^\\/(?!\\.\\.)((?!\\/\\.\\.\\/).)+$": { + "type": "object", + "required": [ + "mode" + ], + "properties": { + "mode": { + "type": "string", + "description": "Symbolic or numeric octal mode" + }, + "recursive": { + "type": "boolean", + "description": "Change modes recursively", + "default": false + } + } + } + } + } + } + } + } +} diff --git a/stages/org.osbuild.chown b/stages/org.osbuild.chown index 9dc8f733..787bbd02 100755 --- a/stages/org.osbuild.chown +++ b/stages/org.osbuild.chown @@ -1,73 +1,9 @@ #!/usr/bin/python3 -""" -Change file owner and group - -Change the file user and/or group ownership of one or more files or directories inside the tree. - -Notes: - - Requires 'chroot' in the buildroot. - - Runs the 'chown' binary from the image in the chroot. -""" - import subprocess import sys import osbuild.api -SCHEMA_2 = r""" -"options": { - "additionalProperties": false, - "properties": { - "items": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^\\/(?!\\.\\.)((?!\\/\\.\\.\\/).)+$": { - "type": "object", - "anyOf": [ - {"required" : ["user"]}, - {"required" : ["group"]} - ], - "properties": { - "user": { - "oneOf": [ - { - "type": "string", - "pattern": "^[A-Za-z0-9_.][A-Za-z0-9_.-]{0,31}$" - }, - { - "type": "number", - "minimum": 0 - } - ], - "description": "User name or UID" - }, - "group": { - "oneOf": [ - { - "type": "string", - "pattern": "^[A-Za-z0-9_][A-Za-z0-9_-]{0,31}$" - }, - { - "type": "number", - "minimum": 0 - } - ], - "description": "Group name or GID" - }, - "recursive": { - "type": "boolean", - "default": false, - "description": "Change ownership recursively" - } - } - } - } - } - } -} -""" - def main(tree, options): for path, cmdargs in options["items"].items(): diff --git a/stages/org.osbuild.chown.meta.json b/stages/org.osbuild.chown.meta.json new file mode 100644 index 00000000..ab507d4d --- /dev/null +++ b/stages/org.osbuild.chown.meta.json @@ -0,0 +1,70 @@ +{ + "summary": "Change file owner and group", + "description": [ + "Change the file user and/or group ownership of one or more files or directories inside the tree.", + "Notes:", + " - Requires 'chroot' in the buildroot.", + " - Runs the 'chown' binary from the image in the chroot." + ], + "schema_2": { + "options": { + "additionalProperties": false, + "properties": { + "items": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + "^\\/(?!\\.\\.)((?!\\/\\.\\.\\/).)+$": { + "type": "object", + "anyOf": [ + { + "required": [ + "user" + ] + }, + { + "required": [ + "group" + ] + } + ], + "properties": { + "user": { + "oneOf": [ + { + "type": "string", + "pattern": "^[A-Za-z0-9_.][A-Za-z0-9_.-]{0,31}$" + }, + { + "type": "number", + "minimum": 0 + } + ], + "description": "User name or UID" + }, + "group": { + "oneOf": [ + { + "type": "string", + "pattern": "^[A-Za-z0-9_][A-Za-z0-9_-]{0,31}$" + }, + { + "type": "number", + "minimum": 0 + } + ], + "description": "Group name or GID" + }, + "recursive": { + "type": "boolean", + "default": false, + "description": "Change ownership recursively" + } + } + } + } + } + } + } + } +} diff --git a/stages/org.osbuild.chrony b/stages/org.osbuild.chrony index ac93cc4c..529bc1ed 100755 --- a/stages/org.osbuild.chrony +++ b/stages/org.osbuild.chrony @@ -1,100 +1,9 @@ #!/usr/bin/python3 -""" -Configure chrony to set system time from the network. - -Configures `chrony` by modifying `/etc/chrony.conf`. - -Before new values are added to the chrony configuration, all lines starting with -"server", "pool" or "peer" are removed. - -The 'timeservers' option provides a very high-level way of configuring chronyd -with specific timeservers. Its value is a list of strings representing the -hostname or IP address of the timeserver. For each list item, the following -line will be added to the configuration: -`server iburst` - -The 'servers' option provides a direct mapping to the `server` directive from -chrony configuration. Its value is a list of dictionaries representing each -timeserver which should be added to the configuration. For each list item, -a `server` directive will be added the configuration. Currently supported -subset of options which can be specified for each timeserver item: - - 'hostname' (REQUIRED) - - 'minpoll' - - 'maxpoll' - - 'iburst' (defaults to true) - - 'prefer' (defaults to false) - -The 'leapsectz' option configures chrony behavior related to automatic checking -of the next occurrence of the leap second, using the provided timezone. Its -value is a string representing a timezone from the system tz database (e.g. -'right/UTC'). If an empty string is provided, then all occurrences of -'leapsectz' directive are removed from the configuration. - -Constraints: - - Exactly one of 'timeservers' or 'servers' options must be provided. -""" - - import re import sys import osbuild.api -SCHEMA = """ -"additionalProperties": false, -"oneOf": [ - {"required": ["timeservers"]}, - {"required": ["servers"]} -], -"properties": { - "timeservers": { - "type": "array", - "items": { "type": "string" }, - "description": "Array of NTP server addresses." - }, - "servers": { - "type": "array", - "items": { - "additionalProperties": false, - "type": "object", - "required": ["hostname"], - "properties": { - "hostname": { - "type": "string", - "description": "Hostname or IP address of a NTP server." - }, - "minpoll": { - "type": "integer", - "description": "Specifies the minimum interval between requests sent to the server as a power of 2 in seconds.", - "minimum": -6, - "maximum": 24 - }, - "maxpoll": { - "type": "integer", - "description": "Specifies the maximum interval between requests sent to the server as a power of 2 in seconds.", - "minimum": -6, - "maximum": 24 - }, - "iburst": { - "type": "boolean", - "default": true, - "description": "Configures chronyd behavior related to burst requests on startup." - }, - "prefer": { - "type": "boolean", - "default": false, - "description": "Prefer this source over sources without the prefer option." - } - } - } - }, - "leapsectz": { - "type": "string", - "description": "Timezone used by chronyd to determine when will the next leap second occur. Empty value will remove the option." - } -} -""" - DELETE_TIME_SOURCE_LINE_REGEX = re.compile(r"(server|pool|peer) ") DELETE_LEAPSECTZ_LINE_REGEX = re.compile(r"leapsectz ") diff --git a/stages/org.osbuild.chrony.meta.json b/stages/org.osbuild.chrony.meta.json new file mode 100644 index 00000000..0e982ef8 --- /dev/null +++ b/stages/org.osbuild.chrony.meta.json @@ -0,0 +1,96 @@ +{ + "summary": "Configure chrony to set system time from the network.", + "description": [ + "Configures `chrony` by modifying `/etc/chrony.conf`.", + "Before new values are added to the chrony configuration, all lines starting with", + "\"server\", \"pool\" or \"peer\" are removed.", + "The 'timeservers' option provides a very high-level way of configuring chronyd", + "with specific timeservers. Its value is a list of strings representing the", + "hostname or IP address of the timeserver. For each list item, the following", + "line will be added to the configuration:", + "`server iburst`", + "The 'servers' option provides a direct mapping to the `server` directive from", + "chrony configuration. Its value is a list of dictionaries representing each", + "timeserver which should be added to the configuration. For each list item,", + "a `server` directive will be added the configuration. Currently supported", + "subset of options which can be specified for each timeserver item:", + " - 'hostname' (REQUIRED)", + " - 'minpoll'", + " - 'maxpoll'", + " - 'iburst' (defaults to true)", + " - 'prefer' (defaults to false)", + "The 'leapsectz' option configures chrony behavior related to automatic checking", + "of the next occurrence of the leap second, using the provided timezone. Its", + "value is a string representing a timezone from the system tz database (e.g.", + "'right/UTC'). If an empty string is provided, then all occurrences of", + "'leapsectz' directive are removed from the configuration.", + "Constraints:", + " - Exactly one of 'timeservers' or 'servers' options must be provided." + ], + "schema": { + "additionalProperties": false, + "oneOf": [ + { + "required": [ + "timeservers" + ] + }, + { + "required": [ + "servers" + ] + } + ], + "properties": { + "timeservers": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Array of NTP server addresses." + }, + "servers": { + "type": "array", + "items": { + "additionalProperties": false, + "type": "object", + "required": [ + "hostname" + ], + "properties": { + "hostname": { + "type": "string", + "description": "Hostname or IP address of a NTP server." + }, + "minpoll": { + "type": "integer", + "description": "Specifies the minimum interval between requests sent to the server as a power of 2 in seconds.", + "minimum": -6, + "maximum": 24 + }, + "maxpoll": { + "type": "integer", + "description": "Specifies the maximum interval between requests sent to the server as a power of 2 in seconds.", + "minimum": -6, + "maximum": 24 + }, + "iburst": { + "type": "boolean", + "default": true, + "description": "Configures chronyd behavior related to burst requests on startup." + }, + "prefer": { + "type": "boolean", + "default": false, + "description": "Prefer this source over sources without the prefer option." + } + } + } + }, + "leapsectz": { + "type": "string", + "description": "Timezone used by chronyd to determine when will the next leap second occur. Empty value will remove the option." + } + } + } +} diff --git a/stages/org.osbuild.clevis.luks-bind b/stages/org.osbuild.clevis.luks-bind index be686c47..0baaf2e7 100755 --- a/stages/org.osbuild.clevis.luks-bind +++ b/stages/org.osbuild.clevis.luks-bind @@ -1,49 +1,10 @@ #!/usr/bin/python3 -""" -Bind a LUKS device using the specified policy. - -Buildhost commands used: `clevis`, `clevis-luks`, `clevis-pin-*`. -""" - - import os import subprocess import sys import osbuild.api -SCHEMA_2 = r""" -"devices": { - "type": "object", - "additionalProperties": true, - "required": ["device"], - "properties": { - "device": { - "type": "object", - "additionalProperties": true - } - } -}, -"options": { - "additionalProperties": false, - "required": ["passphrase", "pin", "policy"], - "properties": { - "passphrase": { - "description": "Passphrase to unlock the container", - "type": "string" - }, - "pin": { - "description": "The pin to use", - "type": "string" - }, - "policy": { - "description": "Policy to use with the given pin", - "type": "string" - } - } -} -""" - def main(devices, options): device = devices["device"] diff --git a/stages/org.osbuild.clevis.luks-bind.meta.json b/stages/org.osbuild.clevis.luks-bind.meta.json new file mode 100644 index 00000000..7c46af41 --- /dev/null +++ b/stages/org.osbuild.clevis.luks-bind.meta.json @@ -0,0 +1,43 @@ +{ + "summary": "Bind a LUKS device using the specified policy.", + "description": [ + "Buildhost commands used: `clevis`, `clevis-luks`, `clevis-pin-*`." + ], + "schema_2": { + "devices": { + "type": "object", + "additionalProperties": true, + "required": [ + "device" + ], + "properties": { + "device": { + "type": "object", + "additionalProperties": true + } + } + }, + "options": { + "additionalProperties": false, + "required": [ + "passphrase", + "pin", + "policy" + ], + "properties": { + "passphrase": { + "description": "Passphrase to unlock the container", + "type": "string" + }, + "pin": { + "description": "The pin to use", + "type": "string" + }, + "policy": { + "description": "Policy to use with the given pin", + "type": "string" + } + } + } + } +} diff --git a/stages/org.osbuild.cloud-init b/stages/org.osbuild.cloud-init index aa986948..0321fe71 100755 --- a/stages/org.osbuild.cloud-init +++ b/stages/org.osbuild.cloud-init @@ -1,146 +1,10 @@ #!/usr/bin/python3 -""" -Configure cloud-init - -The 'config' option allows to configure cloud-init by creating a -configuration file under `/etc/cloud/cloud.cfg.d` with the name -specified by `filename`. - -Constrains: - - Each configuration file definition must contain at least one configuration - -Currently supported subset of cloud-init configuration: - - 'system_info' section - - 'default_user' section - - 'name' option -""" - - import sys import yaml import osbuild.api -SCHEMA = r""" -"definitions": { - "reporting_handlers": { - "type": "string", - "enum": ["log", "print", "webhook", "hyperv"] - } -}, -"additionalProperties": false, -"required": ["config", "filename"], -"properties": { - "filename": { - "type": "string", - "description": "Name of the cloud-init configuration file.", - "pattern": "^[\\w.-]{1,251}\\.cfg$" - }, - "config": { - "additionalProperties": false, - "type": "object", - "description": "cloud-init configuration", - "minProperties": 1, - "properties": { - "system_info": { - "additionalProperties": false, - "type": "object", - "description": "'system_info' configuration section.", - "minProperties": 1, - "properties": { - "default_user": { - "additionalProperties": false, - "type": "object", - "description": "Configuration of the 'default' user created by cloud-init.", - "minProperties": 1, - "properties": { - "name": { - "type": "string", - "description": "username of the 'default' user." - } - } - } - } - }, - "reporting": { - "type": "object", - "additionalProperties": false, - "description": "Define reporting endpoints.", - "minProperties": 1, - "properties": { - "logging": { - "type": "object", - "additionalProperties": false, - "properties": { - "type": { - "$ref": "#/definitions/reporting_handlers" - } - } - }, - "telemetry": { - "type": "object", - "additionalProperties": false, - "properties": { - "type": { - "$ref": "#/definitions/reporting_handlers" - } - } - } - } - }, - "datasource_list": { - "type": "array", - "items": { - "type": "string", - "enum": ["Azure"] - } - }, - "datasource": { - "type": "object", - "description": "Sources of configuration data for cloud-init.", - "minProperties": 1, - "properties": { - "Azure": { - "type": "object", - "minProperties": 1, - "properties": { - "apply_network_config": { - "type": "boolean", - "description": "Whether to use network configuration described by Azure’s IMDS endpoint", - "default": true - } - } - } - } - }, - "output": { - "type": "object", - "minProperties": 1, - "properties": { - "init": { - "description": "Redirect the output of the init stage", - "type": "string" - }, - "config": { - "description": "Redirect the output of the config stage", - "type": "string" - }, - "final": { - "description": "Redirect the output of the final stage", - "type": "string" - }, - "all": { - "description": "Redirect the output of all stages", - "type": "string" - } - } - } - } - } -} -""" - # Class representing the 'datasource_list' configuration option, # allowing to define a custom YAML dumper for it. diff --git a/stages/org.osbuild.cloud-init.meta.json b/stages/org.osbuild.cloud-init.meta.json new file mode 100644 index 00000000..55502616 --- /dev/null +++ b/stages/org.osbuild.cloud-init.meta.json @@ -0,0 +1,142 @@ +{ + "summary": "Configure cloud-init", + "description": [ + "The 'config' option allows to configure cloud-init by creating a", + "configuration file under `/etc/cloud/cloud.cfg.d` with the name", + "specified by `filename`.", + "Constrains:", + " - Each configuration file definition must contain at least one configuration", + "Currently supported subset of cloud-init configuration:", + " - 'system_info' section", + " - 'default_user' section", + " - 'name' option" + ], + "schema": { + "definitions": { + "reporting_handlers": { + "type": "string", + "enum": [ + "log", + "print", + "webhook", + "hyperv" + ] + } + }, + "additionalProperties": false, + "required": [ + "config", + "filename" + ], + "properties": { + "filename": { + "type": "string", + "description": "Name of the cloud-init configuration file.", + "pattern": "^[\\w.-]{1,251}\\.cfg$" + }, + "config": { + "additionalProperties": false, + "type": "object", + "description": "cloud-init configuration", + "minProperties": 1, + "properties": { + "system_info": { + "additionalProperties": false, + "type": "object", + "description": "'system_info' configuration section.", + "minProperties": 1, + "properties": { + "default_user": { + "additionalProperties": false, + "type": "object", + "description": "Configuration of the 'default' user created by cloud-init.", + "minProperties": 1, + "properties": { + "name": { + "type": "string", + "description": "username of the 'default' user." + } + } + } + } + }, + "reporting": { + "type": "object", + "additionalProperties": false, + "description": "Define reporting endpoints.", + "minProperties": 1, + "properties": { + "logging": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "$ref": "#/definitions/reporting_handlers" + } + } + }, + "telemetry": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "$ref": "#/definitions/reporting_handlers" + } + } + } + } + }, + "datasource_list": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "Azure" + ] + } + }, + "datasource": { + "type": "object", + "description": "Sources of configuration data for cloud-init.", + "minProperties": 1, + "properties": { + "Azure": { + "type": "object", + "minProperties": 1, + "properties": { + "apply_network_config": { + "type": "boolean", + "description": "Whether to use network configuration described by Azure\u2019s IMDS endpoint", + "default": true + } + } + } + } + }, + "output": { + "type": "object", + "minProperties": 1, + "properties": { + "init": { + "description": "Redirect the output of the init stage", + "type": "string" + }, + "config": { + "description": "Redirect the output of the config stage", + "type": "string" + }, + "final": { + "description": "Redirect the output of the final stage", + "type": "string" + }, + "all": { + "description": "Redirect the output of all stages", + "type": "string" + } + } + } + } + } + } + } +} diff --git a/stages/org.osbuild.container-deploy b/stages/org.osbuild.container-deploy index df914a3b..2a3bae8b 100755 --- a/stages/org.osbuild.container-deploy +++ b/stages/org.osbuild.container-deploy @@ -1,9 +1,4 @@ #!/usr/bin/python3 -""" -Deploy a container. - -Buildhost commands used: podman skopeo -""" import contextlib import os import random @@ -14,33 +9,6 @@ import sys import osbuild.api from osbuild.util import containers -SCHEMA_2 = r""" -"inputs": { - "type": "object", - "additionalProperties": false, - "required": ["images"], - "properties": { - "images": { - "type": "object", - "additionalProperties": true - } - } -}, -"options": { - "additionalProperties": false, - "properties": { - "exclude": { - "type": "array", - "description": "Exclude paths from the deployment", - "minItems": 1, - "items": { - "type": "string" - } - } - } -} -""" - @contextlib.contextmanager def mount_container(image_tag): diff --git a/stages/org.osbuild.container-deploy.meta.json b/stages/org.osbuild.container-deploy.meta.json new file mode 100644 index 00000000..f52a1bfc --- /dev/null +++ b/stages/org.osbuild.container-deploy.meta.json @@ -0,0 +1,34 @@ +{ + "summary": "Deploy a container.", + "description": [ + "Buildhost commands used: podman skopeo" + ], + "schema_2": { + "inputs": { + "type": "object", + "additionalProperties": false, + "required": [ + "images" + ], + "properties": { + "images": { + "type": "object", + "additionalProperties": true + } + } + }, + "options": { + "additionalProperties": false, + "properties": { + "exclude": { + "type": "array", + "description": "Exclude paths from the deployment", + "minItems": 1, + "items": { + "type": "string" + } + } + } + } + } +} diff --git a/stages/org.osbuild.containers.storage.conf b/stages/org.osbuild.containers.storage.conf index f6230743..aa062b6d 100755 --- a/stages/org.osbuild.containers.storage.conf +++ b/stages/org.osbuild.containers.storage.conf @@ -1,12 +1,4 @@ #!/usr/bin/python3 -""" -Edit containers-storage.conf(5) files. - -This stage can be used to create or modify `containers-storage.conf` -configuration files. The default strategy is to merge the specified -options with the existing options. -""" - import contextlib import os import sys @@ -19,126 +11,6 @@ except ModuleNotFoundError: import osbuild.api -SCHEMA = r""" -"definitions": { - "storage": { - "type": "object", - "additionalProperties": false, - "minProperties": 1, - "properties": { - "driver": { - "description": "container storage driver.", - "type": "string", - "enum": [ - "overlay", - "vfs", - "devmapper", - "aufs", - "btrfs", - "zfs" - ] - }, - "graphroot": { - "description": "container storage graph directory.", - "type": "string" - }, - "runroot": { - "description": "container storage run directory.", - "type": "string" - }, - "transient_store": { - "description": "Make the container store not persist across reboot.", - "type": "boolean" - }, - "options": { - "$ref": "#/definitions/storage-options" - } - } - }, - "storage-options": { - "type": "object", - "additionalProperties": false, - "minProperties": 1, - "properties": { - "additionalimagestores": { - "type": "array", - "items": { - "type": "string" - } - }, - "pull_options": { - "$ref": "#/definitions/storage-options-pulloptions" - }, - "overlay": { - "$ref": "#/definitions/storage-options-overlay" - } - } - }, - "storage-options-pulloptions": { - "type": "object", - "additionalProperties": false, - "minProperties": 1, - "properties": { - "enable_partial_images": { - "type": "string", - "enum": ["true", "false"] - }, - "use_hard_links": { - "type": "string", - "enum": ["true", "false"] - }, - "convert_images": { - "type": "string", - "enum": ["true", "false"] - } - } - }, - "storage-options-overlay": { - "type": "object", - "additionalProperties": false, - "minProperties": 1, - "properties": { - "mountopt": { - "type": "string" - } - } - } -}, -"additionalProperties": false, -"required": ["config"], -"properties": { - "filename": { - "type": "string", - "description": "location of the configuration file.", - "default": "/etc/containers/storage.conf", - "enum": [ - "/etc/containers/storage.conf", - "/usr/share/containers/storage.conf" - ] - }, - "filebase": { - "type": "string", - "description": "Read the base configuration from this file." - }, - "comment": { - "type": "array", - "items": { - "type": "string" - } - }, - "config": { - "additionalProperties": false, - "type": "object", - "description": "storage configuration", - "minProperties": 1, - "properties": { - "storage": { - "$ref": "#/definitions/storage" - } - } - } -} -""" DEFAULT_LOCATION = "/etc/containers/storage.conf" diff --git a/stages/org.osbuild.containers.storage.conf.meta.json b/stages/org.osbuild.containers.storage.conf.meta.json new file mode 100644 index 00000000..8d331e76 --- /dev/null +++ b/stages/org.osbuild.containers.storage.conf.meta.json @@ -0,0 +1,139 @@ +{ + "summary": "Edit containers-storage.conf(5) files.", + "description": [ + "This stage can be used to create or modify `containers-storage.conf`", + "configuration files. The default strategy is to merge the specified", + "options with the existing options." + ], + "schema": { + "definitions": { + "storage": { + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + "driver": { + "description": "container storage driver.", + "type": "string", + "enum": [ + "overlay", + "vfs", + "devmapper", + "aufs", + "btrfs", + "zfs" + ] + }, + "graphroot": { + "description": "container storage graph directory.", + "type": "string" + }, + "runroot": { + "description": "container storage run directory.", + "type": "string" + }, + "transient_store": { + "description": "Make the container store not persist across reboot.", + "type": "boolean" + }, + "options": { + "$ref": "#/definitions/storage-options" + } + } + }, + "storage-options": { + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + "additionalimagestores": { + "type": "array", + "items": { + "type": "string" + } + }, + "pull_options": { + "$ref": "#/definitions/storage-options-pulloptions" + }, + "overlay": { + "$ref": "#/definitions/storage-options-overlay" + } + } + }, + "storage-options-pulloptions": { + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + "enable_partial_images": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "use_hard_links": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "convert_images": { + "type": "string", + "enum": [ + "true", + "false" + ] + } + } + }, + "storage-options-overlay": { + "type": "object", + "additionalProperties": false, + "minProperties": 1, + "properties": { + "mountopt": { + "type": "string" + } + } + } + }, + "additionalProperties": false, + "required": [ + "config" + ], + "properties": { + "filename": { + "type": "string", + "description": "location of the configuration file.", + "default": "/etc/containers/storage.conf", + "enum": [ + "/etc/containers/storage.conf", + "/usr/share/containers/storage.conf" + ] + }, + "filebase": { + "type": "string", + "description": "Read the base configuration from this file." + }, + "comment": { + "type": "array", + "items": { + "type": "string" + } + }, + "config": { + "additionalProperties": false, + "type": "object", + "description": "storage configuration", + "minProperties": 1, + "properties": { + "storage": { + "$ref": "#/definitions/storage" + } + } + } + } + } +} diff --git a/stages/org.osbuild.copy b/stages/org.osbuild.copy index 5bc9067f..90766a14 100755 --- a/stages/org.osbuild.copy +++ b/stages/org.osbuild.copy @@ -1,24 +1,4 @@ #!/usr/bin/python3 -""" -Copy items - -Stage to copy items, that is files or trees, from inputs to mount -points or the tree. Multiple items can be copied. The source and -destination is an url. Supported locations ('schemes') are `tree`, -`mount` and `input`. -The path format follows the rsync convention that if the paths -ends with a slash `/` the content of that directory is copied not -the directory itself. - -Note that the stage by default does not remove the destination -before copying. As a result, if the destination is an existing -symlink to a file, then this file will be overwritten, instead of -the symlink being replaced. If you want to replace the symlink -with a file, you need to set the `remove_destination` option to -`true`. This option works only for files, not directories or -symlinks to directories. -""" - import os import subprocess import sys @@ -27,79 +7,6 @@ from urllib.parse import ParseResult, urlparse import osbuild.api -CAPABILITIES = ["CAP_MAC_ADMIN"] - - -SCHEMA_2 = r""" -"options": { - "additionalProperties": false, - "required": ["paths"], - "properties": { - "paths": { - "description": "Array of items to copy", - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["from", "to"], - "properties": { - "from": { - "oneOf": [ - { - "type": "string", - "description": "The source, if an input", - "pattern": "^input:\/\/[^\/]+\/" - }, - { - "type": "string", - "description": "The source, if a mount", - "pattern": "^mount:\/\/[^\/]+\/" - }, - { - "type": "string", - "description": "The source, if the tree", - "pattern": "^tree:\/\/\/" - } - ] - }, - "to": { - "oneOf": [ - { - "type": "string", - "description": "The destination, if a mount", - "pattern": "^mount:\/\/[^\/]+\/" - }, - { - "type": "string", - "description": "The destination, if the tree", - "pattern": "^tree:\/\/\/" - } - ] - }, - "remove_destination": { - "type": "boolean", - "description": "Remove the destination before copying. Works only for files, not directories.", - "default": false - } - } - } - } - } -}, -"devices": { - "type": "object", - "additionalProperties": true -}, -"mounts": { - "type": "array" -}, -"inputs": { - "type": "object", - "additionalProperties": true -} -""" - def parse_mount(url: ParseResult, args: Dict): name = url.netloc diff --git a/stages/org.osbuild.copy.meta.json b/stages/org.osbuild.copy.meta.json new file mode 100644 index 00000000..d8e2b51f --- /dev/null +++ b/stages/org.osbuild.copy.meta.json @@ -0,0 +1,96 @@ +{ + "summary": "Copy items", + "description": [ + "Stage to copy items, that is files or trees, from inputs to mount", + "points or the tree. Multiple items can be copied. The source and", + "destination is an url. Supported locations ('schemes') are `tree`,", + "`mount` and `input`.", + "The path format follows the rsync convention that if the paths", + "ends with a slash `/` the content of that directory is copied not", + "the directory itself.", + "Note that the stage by default does not remove the destination", + "before copying. As a result, if the destination is an existing", + "symlink to a file, then this file will be overwritten, instead of", + "the symlink being replaced. If you want to replace the symlink", + "with a file, you need to set the `remove_destination` option to", + "`true`. This option works only for files, not directories or", + "symlinks to directories." + ], + "capabilities": [ + "CAP_MAC_ADMIN" + ], + "schema_2": { + "options": { + "additionalProperties": false, + "required": [ + "paths" + ], + "properties": { + "paths": { + "description": "Array of items to copy", + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "from", + "to" + ], + "properties": { + "from": { + "oneOf": [ + { + "type": "string", + "description": "The source, if an input", + "pattern": "^input://[^/]+/" + }, + { + "type": "string", + "description": "The source, if a mount", + "pattern": "^mount://[^/]+/" + }, + { + "type": "string", + "description": "The source, if the tree", + "pattern": "^tree:///" + } + ] + }, + "to": { + "oneOf": [ + { + "type": "string", + "description": "The destination, if a mount", + "pattern": "^mount://[^/]+/" + }, + { + "type": "string", + "description": "The destination, if the tree", + "pattern": "^tree:///" + } + ] + }, + "remove_destination": { + "type": "boolean", + "description": "Remove the destination before copying. Works only for files, not directories.", + "default": false + } + } + } + } + } + }, + "devices": { + "type": "object", + "additionalProperties": true + }, + "mounts": { + "type": "array" + }, + "inputs": { + "type": "object", + "additionalProperties": true + } + } +} diff --git a/stages/org.osbuild.coreos.platform b/stages/org.osbuild.coreos.platform index b21b1f67..7b4be11f 100755 --- a/stages/org.osbuild.coreos.platform +++ b/stages/org.osbuild.coreos.platform @@ -1,27 +1,4 @@ #!/usr/bin/python3 -""" -Setup a CoreOS platform - -In CoreOS we have the concept of a platform (i.e. AWS, GCP, Metal, QEMU) -where each platform has its own provided disk image with slightly -differing settings/behavior. This stage will perform the necessary -configuration for the given platform. This configuration boils down to -a few steps: -1. Locate the source of platform specific information that is provided - in the CoreOS filesystem tree already (the platforms.json). -2. Copy the platforms.json file into the /boot/ partition, which is - sometimes used by coreos-installer. -3. Read the platforms.json to fetch and platform specific kernel - arguments or grub configuration to set. These arguments/config - are primarily console settings. -4. Apply any platform specific kernel arguments along with the - `ignition.platform.id={platform-name}` kernel argument. -5. Create the grub console.cfg file and apply any platform - specific grub console configuration. -This stage is highly CoreOS specific and subject to change in the -future if/when we change the way platform specific information is -defined in our broader efforts to share more defaults with OSBuild. -""" import json import os import shutil @@ -30,24 +7,6 @@ import sys import osbuild.api from osbuild.util import bls -SCHEMA_2 = r""" -"options": { - "additionalProperties": false, - "properties": { - "platform": { - "description": "The target platform name/ID", - "type": "string" - } - } -}, -"devices": { - "type": "object", - "additionalProperties": true -}, -"mounts": { - "type": "array" -} -""" # Constants # For console.cfg see https://github.com/coreos/bootupd/pull/620 diff --git a/stages/org.osbuild.coreos.platform.meta.json b/stages/org.osbuild.coreos.platform.meta.json new file mode 100644 index 00000000..de1a6931 --- /dev/null +++ b/stages/org.osbuild.coreos.platform.meta.json @@ -0,0 +1,42 @@ +{ + "summary": "Setup a CoreOS platform", + "description": [ + "In CoreOS we have the concept of a platform (i.e. AWS, GCP, Metal, QEMU)", + "where each platform has its own provided disk image with slightly", + "differing settings/behavior. This stage will perform the necessary", + "configuration for the given platform. This configuration boils down to", + "a few steps:", + "1. Locate the source of platform specific information that is provided", + " in the CoreOS filesystem tree already (the platforms.json).", + "2. Copy the platforms.json file into the /boot/ partition, which is", + " sometimes used by coreos-installer.", + "3. Read the platforms.json to fetch and platform specific kernel", + " arguments or grub configuration to set. These arguments/config", + " are primarily console settings.", + "4. Apply any platform specific kernel arguments along with the", + " `ignition.platform.id={platform-name}` kernel argument.", + "5. Create the grub console.cfg file and apply any platform", + " specific grub console configuration.", + "This stage is highly CoreOS specific and subject to change in the", + "future if/when we change the way platform specific information is", + "defined in our broader efforts to share more defaults with OSBuild." + ], + "schema_2": { + "options": { + "additionalProperties": false, + "properties": { + "platform": { + "description": "The target platform name/ID", + "type": "string" + } + } + }, + "devices": { + "type": "object", + "additionalProperties": true + }, + "mounts": { + "type": "array" + } + } +} diff --git a/stages/org.osbuild.cpio.out b/stages/org.osbuild.cpio.out index f111e644..0a488052 100755 --- a/stages/org.osbuild.cpio.out +++ b/stages/org.osbuild.cpio.out @@ -1,80 +1,10 @@ #!/usr/bin/python3 -""" -Assembles the tree into a CPIO archive. - -Uses the buildhost's `cpio` command, to create an archive -at `filename` with the contents of the input `tree`. If -`append` is `true`, its files will be added to an existing -archive. The default format is `newc` , the "new (SVR4) -portable format", which is also used by `dracut`(8). - -Buildhost commands used: `cpio` -""" - import os import subprocess import sys import osbuild.api -SCHEMA_2 = """ -"options": { - "additionalProperties": false, - "required": ["filename"], - "properties": { - "filename": { - "description": "Filename for tar archive", - "type": "string" - }, - "append": { - "type": "boolean", - "description": "Append to an existing archive.", - "default": false - }, - "format": { - "description": "Archive format to use", - "type": "string", - "enum": ["bin", "odc", "newc", "crc", "tar", "ustar"], - "default": "newc" - }, - "root-node": { - "description": "How to handle the root node: include or omit", - "enum": ["include", "omit"], - "default": "include" - }, - "reproducible": { - "type": "boolean", - "description": "Produce device-independent, reproducible archives.", - "default": true - }, - "owner": { - "type": "object", - "additionalProperties": false, - "required": ["user"], - "properties": { - "user": { - "type": "string" - }, - "group": { - "type": "string" - } - } - } - } -}, -"inputs": { - "type": "object", - "additionalProperties": false, - "required": ["tree"], - "properties": { - "tree": { - "type": "object", - "additionalProperties": true - } - } -} -""" - def iter_files(tree, include): for root, _, files in os.walk(tree, topdown=True): diff --git a/stages/org.osbuild.cpio.out.meta.json b/stages/org.osbuild.cpio.out.meta.json new file mode 100644 index 00000000..52d17d32 --- /dev/null +++ b/stages/org.osbuild.cpio.out.meta.json @@ -0,0 +1,84 @@ +{ + "summary": "Assembles the tree into a CPIO archive.", + "description": [ + "Uses the buildhost's `cpio` command, to create an archive", + "at `filename` with the contents of the input `tree`. If", + "`append` is `true`, its files will be added to an existing", + "archive. The default format is `newc` , the \"new (SVR4)", + "portable format\", which is also used by `dracut`(8).", + "Buildhost commands used: `cpio`" + ], + "schema_2": { + "options": { + "additionalProperties": false, + "required": [ + "filename" + ], + "properties": { + "filename": { + "description": "Filename for tar archive", + "type": "string" + }, + "append": { + "type": "boolean", + "description": "Append to an existing archive.", + "default": false + }, + "format": { + "description": "Archive format to use", + "type": "string", + "enum": [ + "bin", + "odc", + "newc", + "crc", + "tar", + "ustar" + ], + "default": "newc" + }, + "root-node": { + "description": "How to handle the root node: include or omit", + "enum": [ + "include", + "omit" + ], + "default": "include" + }, + "reproducible": { + "type": "boolean", + "description": "Produce device-independent, reproducible archives.", + "default": true + }, + "owner": { + "type": "object", + "additionalProperties": false, + "required": [ + "user" + ], + "properties": { + "user": { + "type": "string" + }, + "group": { + "type": "string" + } + } + } + } + }, + "inputs": { + "type": "object", + "additionalProperties": false, + "required": [ + "tree" + ], + "properties": { + "tree": { + "type": "object", + "additionalProperties": true + } + } + } + } +} diff --git a/stages/org.osbuild.cron.script b/stages/org.osbuild.cron.script index 46ba1080..3b405e00 100755 --- a/stages/org.osbuild.cron.script +++ b/stages/org.osbuild.cron.script @@ -1,59 +1,9 @@ #!/usr/bin/python3 -""" -Run a script at regular intervals. - -Execute a script at regular intervals. This uses the cron drop-in -directories in etc, which correspond to the supported intervals: - `cron.hourly/`, `cron.daily/`, `cron.weekly/`, `cron.monthly/` - -NB: Does itself not create the directories so they must be created -via the package that provides the facility, like `cronie` or on -older systems `crontabs`. -""" - - import os import sys import osbuild.api -SCHEMA_2 = r""" -"options": { - "additionalProperties": false, - "required": ["interval", "filename"], - "oneOf": [ - {"required": ["simple"]} - ], - "properties": { - "interval": { - "type": "string", - "enum": ["hourly", "daily", "weekly", "monthly"] - }, - "filename": { - "type": "string", - "description": "Name of the cron script", - "pattern": "^[\\w.-]{1,255}$" - }, - "simple": { - "type": "object", - "description": "A simple command to run.", - "required": ["command"], - "properties": { - "comment": { - "type": "array", - "items": { - "type": "string" - } - }, - "command": { - "type": "string" - } - } - } - } -} -""" - def format_comment(comment): lines = comment.split("\n") diff --git a/stages/org.osbuild.cron.script.meta.json b/stages/org.osbuild.cron.script.meta.json new file mode 100644 index 00000000..951a85a8 --- /dev/null +++ b/stages/org.osbuild.cron.script.meta.json @@ -0,0 +1,61 @@ +{ + "summary": "Run a script at regular intervals.", + "description": [ + "Execute a script at regular intervals. This uses the cron drop-in", + "directories in etc, which correspond to the supported intervals:", + " `cron.hourly/`, `cron.daily/`, `cron.weekly/`, `cron.monthly/`", + "NB: Does itself not create the directories so they must be created", + "via the package that provides the facility, like `cronie` or on", + "older systems `crontabs`." + ], + "schema_2": { + "options": { + "additionalProperties": false, + "required": [ + "interval", + "filename" + ], + "oneOf": [ + { + "required": [ + "simple" + ] + } + ], + "properties": { + "interval": { + "type": "string", + "enum": [ + "hourly", + "daily", + "weekly", + "monthly" + ] + }, + "filename": { + "type": "string", + "description": "Name of the cron script", + "pattern": "^[\\w.-]{1,255}$" + }, + "simple": { + "type": "object", + "description": "A simple command to run.", + "required": [ + "command" + ], + "properties": { + "comment": { + "type": "array", + "items": { + "type": "string" + } + }, + "command": { + "type": "string" + } + } + } + } + } + } +} diff --git a/stages/org.osbuild.crypttab b/stages/org.osbuild.crypttab index 7a74f44c..9b8b41bc 100755 --- a/stages/org.osbuild.crypttab +++ b/stages/org.osbuild.crypttab @@ -1,66 +1,8 @@ #!/usr/bin/python3 -""" -Create /etc/crypttab entries for encrypted block devices - -See crypttab(5) for a detailed description of the format but in brief: -each item in the list of `volumes` describes an encrypted block device -and how it should it should be setup. The block device is identified -either by `uuid` or by `path` (device node path). The volume will be -named as `volume`, i.e. made available as `/dev/mapper/$volume`. -Additionally, a keyfile can (optionally) be specified via `keyfile`. -Specific device options can be specified via `options`. - -This stage replaces /etc/crypttab, removing any existing entries. -""" - - import sys import osbuild.api -SCHEMA = """ -"additionalProperties": false, -"required": ["volumes"], -"properties": { - "volumes": { - "type": "array", - "description": "array of volume objects", - "items": { - "type": "object", - "oneOf": [{ - "required": ["uuid", "volume"] - }, { - "required": ["path", "volume"] - }], - "properties": { - "volume": { - "description": "volume mountpoint", - "type": "string" - }, - "uuid": { - "description": "device UUID", - "type": "string" - }, - "path": { - "description": "device path", - "type": "string" - }, - "keyfile": { - "description": "", - "type": "string", - "default": "none" - }, - "options": { - "description": "options (comma-separated)", - "type": "string", - "default": "" - } - } - } - } -} -""" - def main(tree, options): volumes = options["volumes"] diff --git a/stages/org.osbuild.crypttab.meta.json b/stages/org.osbuild.crypttab.meta.json new file mode 100644 index 00000000..54089619 --- /dev/null +++ b/stages/org.osbuild.crypttab.meta.json @@ -0,0 +1,66 @@ +{ + "summary": "Create /etc/crypttab entries for encrypted block devices", + "description": [ + "See crypttab(5) for a detailed description of the format but in brief:", + "each item in the list of `volumes` describes an encrypted block device", + "and how it should it should be setup. The block device is identified", + "either by `uuid` or by `path` (device node path). The volume will be", + "named as `volume`, i.e. made available as `/dev/mapper/$volume`.", + "Additionally, a keyfile can (optionally) be specified via `keyfile`.", + "Specific device options can be specified via `options`.", + "This stage replaces /etc/crypttab, removing any existing entries." + ], + "schema": { + "additionalProperties": false, + "required": [ + "volumes" + ], + "properties": { + "volumes": { + "type": "array", + "description": "array of volume objects", + "items": { + "type": "object", + "oneOf": [ + { + "required": [ + "uuid", + "volume" + ] + }, + { + "required": [ + "path", + "volume" + ] + } + ], + "properties": { + "volume": { + "description": "volume mountpoint", + "type": "string" + }, + "uuid": { + "description": "device UUID", + "type": "string" + }, + "path": { + "description": "device path", + "type": "string" + }, + "keyfile": { + "description": "", + "type": "string", + "default": "none" + }, + "options": { + "description": "options (comma-separated)", + "type": "string", + "default": "" + } + } + } + } + } + } +} diff --git a/stages/org.osbuild.debug-shell b/stages/org.osbuild.debug-shell index 0935a885..f1cdc8dd 100755 --- a/stages/org.osbuild.debug-shell +++ b/stages/org.osbuild.debug-shell @@ -1,30 +1,9 @@ #!/usr/bin/python3 -""" -Set up an early root shell on a certain tty - -Creates a systemd unit file at /etc/systemd/system/osbuild-debug-shell.service -which starts an early-boot root shell on the given `tty`. - -Also symlinks the service file into /etc/systemd/system/sysinit.target.wants/. -""" - - import os import sys import osbuild.api -SCHEMA = """ -"additionalProperties": false, -"required": ["tty"], -"properties": { - "tty": { - "type": "string", - "description": "Absolute path of the tty device to start a root shell on." - } -} -""" - def main(tree, options): tty = options["tty"] diff --git a/stages/org.osbuild.debug-shell.meta.json b/stages/org.osbuild.debug-shell.meta.json new file mode 100644 index 00000000..e4f93a8f --- /dev/null +++ b/stages/org.osbuild.debug-shell.meta.json @@ -0,0 +1,20 @@ +{ + "summary": "Set up an early root shell on a certain tty", + "description": [ + "Creates a systemd unit file at /etc/systemd/system/osbuild-debug-shell.service", + "which starts an early-boot root shell on the given `tty`.", + "Also symlinks the service file into /etc/systemd/system/sysinit.target.wants/." + ], + "schema": { + "additionalProperties": false, + "required": [ + "tty" + ], + "properties": { + "tty": { + "type": "string", + "description": "Absolute path of the tty device to start a root shell on." + } + } + } +} diff --git a/stages/org.osbuild.discinfo b/stages/org.osbuild.discinfo index 5376c53b..db50b97c 100755 --- a/stages/org.osbuild.discinfo +++ b/stages/org.osbuild.discinfo @@ -1,31 +1,10 @@ #!/usr/bin/python3 -""" -Create a `.discinfo` file describing disk - -This will create a `.discinfo` file with the specified parameters. -""" - import os import sys import time import osbuild.api -SCHEMA = """ -"additionalProperties": true, -"required": ["basearch", "release"], -"properties": { - "basearch": { - "description": "Build architecture.", - "type": "string" - }, - "release": { - "description": "The product name.", - "type": "string" - } -} -""" - def main(tree, options): basearch = options["basearch"] diff --git a/stages/org.osbuild.discinfo.meta.json b/stages/org.osbuild.discinfo.meta.json new file mode 100644 index 00000000..3d2fc6d9 --- /dev/null +++ b/stages/org.osbuild.discinfo.meta.json @@ -0,0 +1,23 @@ +{ + "summary": "Create a `.discinfo` file describing disk", + "description": [ + "This will create a `.discinfo` file with the specified parameters." + ], + "schema": { + "additionalProperties": true, + "required": [ + "basearch", + "release" + ], + "properties": { + "basearch": { + "description": "Build architecture.", + "type": "string" + }, + "release": { + "description": "The product name.", + "type": "string" + } + } + } +} diff --git a/stages/org.osbuild.dnf-automatic.config b/stages/org.osbuild.dnf-automatic.config index 518ed2df..f5a4e960 100755 --- a/stages/org.osbuild.dnf-automatic.config +++ b/stages/org.osbuild.dnf-automatic.config @@ -1,56 +1,10 @@ #!/usr/bin/python3 -""" -Change DNF Automatic configuration. - -The stage changes persistent DNF Automatic configuration. Currently, only -a subset of options can be set: - - 'commands' section - - apply_updates - - upgrade_type -""" - - import sys import iniparse import osbuild.api -SCHEMA = r""" -"definitions": { - "commands": { - "type": "object", - "additionalProperties": false, - "description": "'commands' configuration section.", - "properties": { - "apply_updates": { - "type": "boolean", - "description": "Whether packages comprising the available updates should be installed." - }, - "upgrade_type": { - "type": "string", - "description": "What kind of upgrades to look at.", - "enum": ["default", "security"] - } - } - } -}, -"additionalProperties": false, -"description": "DNF Automatic configuration.", -"properties": { - "config": { - "type": "object", - "additionalProperties": false, - "description": "configuration definition.", - "properties": { - "commands": { - "$ref": "#/definitions/commands" - } - } - } -} -""" - def bool_to_yes_no(b): if b: diff --git a/stages/org.osbuild.dnf-automatic.config.meta.json b/stages/org.osbuild.dnf-automatic.config.meta.json new file mode 100644 index 00000000..269b4505 --- /dev/null +++ b/stages/org.osbuild.dnf-automatic.config.meta.json @@ -0,0 +1,47 @@ +{ + "summary": "Change DNF Automatic configuration.", + "description": [ + "The stage changes persistent DNF Automatic configuration. Currently, only", + "a subset of options can be set:", + " - 'commands' section", + " - apply_updates", + " - upgrade_type" + ], + "schema": { + "definitions": { + "commands": { + "type": "object", + "additionalProperties": false, + "description": "'commands' configuration section.", + "properties": { + "apply_updates": { + "type": "boolean", + "description": "Whether packages comprising the available updates should be installed." + }, + "upgrade_type": { + "type": "string", + "description": "What kind of upgrades to look at.", + "enum": [ + "default", + "security" + ] + } + } + } + }, + "additionalProperties": false, + "description": "DNF Automatic configuration.", + "properties": { + "config": { + "type": "object", + "additionalProperties": false, + "description": "configuration definition.", + "properties": { + "commands": { + "$ref": "#/definitions/commands" + } + } + } + } + } +} diff --git a/stages/org.osbuild.dnf.config b/stages/org.osbuild.dnf.config index a3de2154..13be9391 100755 --- a/stages/org.osbuild.dnf.config +++ b/stages/org.osbuild.dnf.config @@ -1,15 +1,4 @@ #!/usr/bin/python3 -""" -Change DNF configuration. - -The stage changes persistent DNF configuration on the filesystem. - -Allows defining dnf variables via the `variables` option and -specific configuration options via the `config` option. The -latter will be saved in `/etc/dnf/dnf.conf`. See `dnf.conf(5)` -for details about the configuration options. -""" - import os import sys @@ -17,79 +6,6 @@ import iniparse import osbuild.api -SCHEMA = r""" -"definitions": { - "variable": { - "type": "object", - "additionalProperties": false, - "required": ["name", "value"], - "description": "DNF variable to configure persistently.", - "properties": { - "name": { - "type": "string", - "pattern": "^[a-z0-9_]+$", - "description": "Name of the variable." - }, - "value": { - "type": "string", - "description": "Value of the variable." - } - } - }, - "config_main": { - "type": "object", - "additionalProperties": false, - "properties": { - "ip_resolve": { - "type": "string", - "enum": ["4", "IPv4", "6", "IPv6"], - "description": "Determines how DNF resolves host names." - }, - "tsflags": { - "type": "array", - "description": "Extra flags for the RPM transaction.", - "minItems": 1, - "uniqueItems": true, - "items": { - "type": "string", - "enum": [ - "noscripts", - "test", - "notriggers", - "nodocs", - "justdb", - "nocontexts", - "nocaps", - "nocrypto" - ] - } - } - } - } -}, -"additionalProperties": false, -"description": "DNF configuration.", -"properties": { - "variables": { - "type": "array", - "description": "DNF variables to configure persistently.", - "items": { - "$ref": "#/definitions/variable" - } - }, - "config": { - "additionalProperties": false, - "type": "object", - "description": "DNF global configuration.", - "properties": { - "main": { - "$ref": "#/definitions/config_main" - } - } - } -} -""" - def configure_variable(tree, name, value): """ diff --git a/stages/org.osbuild.dnf.config.meta.json b/stages/org.osbuild.dnf.config.meta.json new file mode 100644 index 00000000..1cf331c1 --- /dev/null +++ b/stages/org.osbuild.dnf.config.meta.json @@ -0,0 +1,90 @@ +{ + "summary": "Change DNF configuration.", + "description": [ + "The stage changes persistent DNF configuration on the filesystem.", + "Allows defining dnf variables via the `variables` option and", + "specific configuration options via the `config` option. The", + "latter will be saved in `/etc/dnf/dnf.conf`. See `dnf.conf(5)`", + "for details about the configuration options." + ], + "schema": { + "definitions": { + "variable": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "value" + ], + "description": "DNF variable to configure persistently.", + "properties": { + "name": { + "type": "string", + "pattern": "^[a-z0-9_]+$", + "description": "Name of the variable." + }, + "value": { + "type": "string", + "description": "Value of the variable." + } + } + }, + "config_main": { + "type": "object", + "additionalProperties": false, + "properties": { + "ip_resolve": { + "type": "string", + "enum": [ + "4", + "IPv4", + "6", + "IPv6" + ], + "description": "Determines how DNF resolves host names." + }, + "tsflags": { + "type": "array", + "description": "Extra flags for the RPM transaction.", + "minItems": 1, + "uniqueItems": true, + "items": { + "type": "string", + "enum": [ + "noscripts", + "test", + "notriggers", + "nodocs", + "justdb", + "nocontexts", + "nocaps", + "nocrypto" + ] + } + } + } + } + }, + "additionalProperties": false, + "description": "DNF configuration.", + "properties": { + "variables": { + "type": "array", + "description": "DNF variables to configure persistently.", + "items": { + "$ref": "#/definitions/variable" + } + }, + "config": { + "additionalProperties": false, + "type": "object", + "description": "DNF global configuration.", + "properties": { + "main": { + "$ref": "#/definitions/config_main" + } + } + } + } + } +} diff --git a/stages/org.osbuild.dnf4.mark b/stages/org.osbuild.dnf4.mark index 03209f08..c2853c47 100755 --- a/stages/org.osbuild.dnf4.mark +++ b/stages/org.osbuild.dnf4.mark @@ -1,43 +1,10 @@ #!/usr/bin/python3 -""" -Mark packages in the DNF state database. -""" - import shutil import subprocess import sys from osbuild import api -SCHEMA_2 = """ -"options": { - "additionalProperties": false, - "properties": { - "packages": { - "type": "array", - "minItems": 1, - "description": "Packages and their marks.", - "items": { - "type": "object", - "additionalProperties": false, - "required": ["name", "mark"], - "properties": { - "name": { - "type": "string", - "description": "Package name." - }, - "mark": { - "type": "string", - "enum": ["install", "group"], - "description": "Package mark." - } - } - } - } - } -} -""" - def mark(tree, packages): dnf_bin = shutil.which("dnf-3") diff --git a/stages/org.osbuild.dnf4.mark.meta.json b/stages/org.osbuild.dnf4.mark.meta.json new file mode 100644 index 00000000..bd1f3226 --- /dev/null +++ b/stages/org.osbuild.dnf4.mark.meta.json @@ -0,0 +1,38 @@ +{ + "summary": "Mark packages in the DNF state database.", + "description": [], + "schema_2": { + "options": { + "additionalProperties": false, + "properties": { + "packages": { + "type": "array", + "minItems": 1, + "description": "Packages and their marks.", + "items": { + "type": "object", + "additionalProperties": false, + "required": [ + "name", + "mark" + ], + "properties": { + "name": { + "type": "string", + "description": "Package name." + }, + "mark": { + "type": "string", + "enum": [ + "install", + "group" + ], + "description": "Package mark." + } + } + } + } + } + } + } +} diff --git a/stages/org.osbuild.dracut b/stages/org.osbuild.dracut index 475970a0..16bc379a 100755 --- a/stages/org.osbuild.dracut +++ b/stages/org.osbuild.dracut @@ -1,141 +1,9 @@ #!/usr/bin/python3 -""" -Create (re-create) the initial RAM file-system - -Uses `dracut` to re-create the initial RAM filesystem, see man dracut(8). -The kernels for which the initramfs should be generated need to be provided -via `kernel` matching their name on the disk, like "5.6.6-300.fc32.x86_64". - -Supports most options also found in `dracut`(8). See the respective man -page and schema for this stage. - -NB: needs chroot for now as well as `strip` for stripping the initrfams. -""" - import subprocess import sys import osbuild.api -SCHEMA = """ -"required": ["kernel"], -"properties": { - "kernel": { - "description": "List of target kernel versions", - "type": "array", - "items": { - "type": "string", - "description": "A kernel version" - } - }, - "compress": { - "description": "Compress the initramfs, passed via `--compress`", - "type": "string" - }, - "modules": { - "description": "Exact list of dracut modules to use.", - "type": "array", - "items": { - "type": "string", - "description": "A dracut module, e.g. base, nfs, network ..." - } - }, - "add_modules": { - "description": "Additional dracut modules to include.", - "type": "array", - "items": { - "type": "string", - "description": "A dracut module, e.g. base, nfs, network ..." - } - }, - "omit_modules": { - "description": "Dracut modules to not include.", - "type": "array", - "items": { - "type": "string", - "description": "A dracut module, e.g. base, nfs, network ..." - } - }, - "drivers": { - "description": "Kernel modules to exclusively include.", - "type": "array", - "items": { - "type": "string", - "description": "A kernel module without the .ko extension" - } - }, - "add_drivers": { - "description": "Add a specific kernel modules.", - "type": "array", - "items": { - "type": "string", - "description": "A kernel module without the .ko extension" - } - }, - "omit_drivers": { - "description": "Omit specific kernel modules.", - "type": "array", - "items": { - "type": "string", - "description": "A kernel module without the .ko extension." - } - }, - "force_drivers": { - "description": "Add driver and ensure that they are tried to be loaded.", - "type": "array", - "items": { - "type": "string", - "description": "A kernel module without the .ko extension" - } - }, - "filesystems": { - "description": "Kernel filesystem modules to exclusively include.", - "type": "array", - "items": { - "type": "string", - "description": "A kernel module without the .ko extension" - } - }, - "include": { - "description": "Add custom files to the initramfs.", - "type": "array", - "items": { - "type": "object", - "description": "What (keys) to include where (values)" - } - }, - "install": { - "description": "Install the specified files.", - "type": "array", - "items": { - "type": "string" - } - }, - "early_microcode": { - "description": "Combine early microcode with the initramfs.", - "type": "boolean", - "default": false - }, - "reproducible": { - "description": "Create reproducible images.", - "type": "boolean" - }, - "initoverlayfs": { - "description": "Use initoverlayfs rather than initramfs, requires initoverlayfs rpm to be installed", - "type": "boolean", - "default": false - }, - "extra": { - "description": "Extra arguments to directly pass to dracut", - "type": "array", - "items": { - "type": "string", - "description": "Individual extra arguments" - } - } -} -""" - def yesno(name: str, value: bool) -> str: prefix = "" if value else "no-" diff --git a/stages/org.osbuild.dracut.conf b/stages/org.osbuild.dracut.conf index 6c36231b..912b07ef 100755 --- a/stages/org.osbuild.dracut.conf +++ b/stages/org.osbuild.dracut.conf @@ -1,138 +1,8 @@ #!/usr/bin/python3 -""" -Configure dracut. - -The 'config' option allows to create a dracut configuration file under -`/usr/lib/dracut/dracut.conf.d/` with the name `filename`. Only a subset -of configuration options is supported, with the intention to provide -functional parity with `org.osbuild.dracut` stage. - -Constrains: - - At least one configuration option must be specified for each configuration - -Supported configuration options: - - compress - - dracutmodules - - add_dracutmodules - - omit_dracutmodules - - drivers - - add_drivers - - omit_drivers - - force_drivers - - filesystems - - install_items - - early_microcode - - reproducible -""" - import sys import osbuild.api -SCHEMA = r""" -"additionalProperties": false, -"required": ["config", "filename"], -"properties": { - "filename": { - "type": "string", - "description": "Name of the dracut configuration file.", - "pattern": "^[\\w.-]{1,250}\\.conf$" - }, - "config": { - "additionalProperties": false, - "type": "object", - "description": "dracut configuration.", - "minProperties": 1, - "properties": { - "compress": { - "description": "Compress the generated initramfs using the passed compression program.", - "type": "string" - }, - "dracutmodules": { - "description": "Exact list of dracut modules to use.", - "type": "array", - "items": { - "type": "string", - "description": "A dracut module, e.g. base, nfs, network ..." - } - }, - "add_dracutmodules": { - "description": "Additional dracut modules to include.", - "type": "array", - "items": { - "type": "string", - "description": "A dracut module, e.g. base, nfs, network ..." - } - }, - "omit_dracutmodules": { - "description": "Dracut modules to not include.", - "type": "array", - "items": { - "type": "string", - "description": "A dracut module, e.g. base, nfs, network ..." - } - }, - "drivers": { - "description": "Kernel modules to exclusively include.", - "type": "array", - "items": { - "type": "string", - "description": "A kernel module without the .ko extension." - } - }, - "add_drivers": { - "description": "Add a specific kernel modules.", - "type": "array", - "items": { - "type": "string", - "description": "A kernel module without the .ko extension." - } - }, - "omit_drivers": { - "description": "Omit specific kernel modules.", - "type": "array", - "items": { - "type": "string", - "description": "A kernel module without the .ko extension." - } - }, - "force_drivers": { - "description": "Add driver and ensure that they are tried to be loaded.", - "type": "array", - "items": { - "type": "string", - "description": "A kernel module without the .ko extension." - } - }, - "filesystems": { - "description": "Kernel filesystem modules to exclusively include.", - "type": "array", - "items": { - "type": "string", - "description": "A kernel module without the .ko extension." - } - }, - "install_items": { - "description": "Install the specified files.", - "type": "array", - "items": { - "type": "string", - "description": "Specify additional files to include in the initramfs." - } - }, - "early_microcode": { - "description": "Combine early microcode with the initramfs.", - "type": "boolean" - }, - "reproducible": { - "description": "Create reproducible images.", - "type": "boolean" - } - } - } -} -""" - def bool_to_string(value): return "yes" if value else "no" diff --git a/stages/org.osbuild.dracut.conf.meta.json b/stages/org.osbuild.dracut.conf.meta.json new file mode 100644 index 00000000..6251f440 --- /dev/null +++ b/stages/org.osbuild.dracut.conf.meta.json @@ -0,0 +1,130 @@ +{ + "summary": "Configure dracut.", + "description": [ + "The 'config' option allows to create a dracut configuration file under", + "`/usr/lib/dracut/dracut.conf.d/` with the name `filename`. Only a subset", + "of configuration options is supported, with the intention to provide", + "functional parity with `org.osbuild.dracut` stage.", + "Constrains:", + " - At least one configuration option must be specified for each configuration", + "Supported configuration options:", + " - compress", + " - dracutmodules", + " - add_dracutmodules", + " - omit_dracutmodules", + " - drivers", + " - add_drivers", + " - omit_drivers", + " - force_drivers", + " - filesystems", + " - install_items", + " - early_microcode", + " - reproducible" + ], + "schema": { + "additionalProperties": false, + "required": [ + "config", + "filename" + ], + "properties": { + "filename": { + "type": "string", + "description": "Name of the dracut configuration file.", + "pattern": "^[\\w.-]{1,250}\\.conf$" + }, + "config": { + "additionalProperties": false, + "type": "object", + "description": "dracut configuration.", + "minProperties": 1, + "properties": { + "compress": { + "description": "Compress the generated initramfs using the passed compression program.", + "type": "string" + }, + "dracutmodules": { + "description": "Exact list of dracut modules to use.", + "type": "array", + "items": { + "type": "string", + "description": "A dracut module, e.g. base, nfs, network ..." + } + }, + "add_dracutmodules": { + "description": "Additional dracut modules to include.", + "type": "array", + "items": { + "type": "string", + "description": "A dracut module, e.g. base, nfs, network ..." + } + }, + "omit_dracutmodules": { + "description": "Dracut modules to not include.", + "type": "array", + "items": { + "type": "string", + "description": "A dracut module, e.g. base, nfs, network ..." + } + }, + "drivers": { + "description": "Kernel modules to exclusively include.", + "type": "array", + "items": { + "type": "string", + "description": "A kernel module without the .ko extension." + } + }, + "add_drivers": { + "description": "Add a specific kernel modules.", + "type": "array", + "items": { + "type": "string", + "description": "A kernel module without the .ko extension." + } + }, + "omit_drivers": { + "description": "Omit specific kernel modules.", + "type": "array", + "items": { + "type": "string", + "description": "A kernel module without the .ko extension." + } + }, + "force_drivers": { + "description": "Add driver and ensure that they are tried to be loaded.", + "type": "array", + "items": { + "type": "string", + "description": "A kernel module without the .ko extension." + } + }, + "filesystems": { + "description": "Kernel filesystem modules to exclusively include.", + "type": "array", + "items": { + "type": "string", + "description": "A kernel module without the .ko extension." + } + }, + "install_items": { + "description": "Install the specified files.", + "type": "array", + "items": { + "type": "string", + "description": "Specify additional files to include in the initramfs." + } + }, + "early_microcode": { + "description": "Combine early microcode with the initramfs.", + "type": "boolean" + }, + "reproducible": { + "description": "Create reproducible images.", + "type": "boolean" + } + } + } + } + } +} diff --git a/stages/org.osbuild.dracut.meta.json b/stages/org.osbuild.dracut.meta.json new file mode 100644 index 00000000..973f39ab --- /dev/null +++ b/stages/org.osbuild.dracut.meta.json @@ -0,0 +1,131 @@ +{ + "summary": "Create (re-create) the initial RAM file-system", + "description": [ + "Uses `dracut` to re-create the initial RAM filesystem, see man dracut(8).", + "The kernels for which the initramfs should be generated need to be provided", + "via `kernel` matching their name on the disk, like \"5.6.6-300.fc32.x86_64\".", + "Supports most options also found in `dracut`(8). See the respective man", + "page and schema for this stage.", + "NB: needs chroot for now as well as `strip` for stripping the initrfams." + ], + "schema": { + "required": [ + "kernel" + ], + "properties": { + "kernel": { + "description": "List of target kernel versions", + "type": "array", + "items": { + "type": "string", + "description": "A kernel version" + } + }, + "compress": { + "description": "Compress the initramfs, passed via `--compress`", + "type": "string" + }, + "modules": { + "description": "Exact list of dracut modules to use.", + "type": "array", + "items": { + "type": "string", + "description": "A dracut module, e.g. base, nfs, network ..." + } + }, + "add_modules": { + "description": "Additional dracut modules to include.", + "type": "array", + "items": { + "type": "string", + "description": "A dracut module, e.g. base, nfs, network ..." + } + }, + "omit_modules": { + "description": "Dracut modules to not include.", + "type": "array", + "items": { + "type": "string", + "description": "A dracut module, e.g. base, nfs, network ..." + } + }, + "drivers": { + "description": "Kernel modules to exclusively include.", + "type": "array", + "items": { + "type": "string", + "description": "A kernel module without the .ko extension" + } + }, + "add_drivers": { + "description": "Add a specific kernel modules.", + "type": "array", + "items": { + "type": "string", + "description": "A kernel module without the .ko extension" + } + }, + "omit_drivers": { + "description": "Omit specific kernel modules.", + "type": "array", + "items": { + "type": "string", + "description": "A kernel module without the .ko extension." + } + }, + "force_drivers": { + "description": "Add driver and ensure that they are tried to be loaded.", + "type": "array", + "items": { + "type": "string", + "description": "A kernel module without the .ko extension" + } + }, + "filesystems": { + "description": "Kernel filesystem modules to exclusively include.", + "type": "array", + "items": { + "type": "string", + "description": "A kernel module without the .ko extension" + } + }, + "include": { + "description": "Add custom files to the initramfs.", + "type": "array", + "items": { + "type": "object", + "description": "What (keys) to include where (values)" + } + }, + "install": { + "description": "Install the specified files.", + "type": "array", + "items": { + "type": "string" + } + }, + "early_microcode": { + "description": "Combine early microcode with the initramfs.", + "type": "boolean", + "default": false + }, + "reproducible": { + "description": "Create reproducible images.", + "type": "boolean" + }, + "initoverlayfs": { + "description": "Use initoverlayfs rather than initramfs, requires initoverlayfs rpm to be installed", + "type": "boolean", + "default": false + }, + "extra": { + "description": "Extra arguments to directly pass to dracut", + "type": "array", + "items": { + "type": "string", + "description": "Individual extra arguments" + } + } + } + } +} diff --git a/stages/org.osbuild.erofs b/stages/org.osbuild.erofs index 2484b714..e52f2c6a 100755 --- a/stages/org.osbuild.erofs +++ b/stages/org.osbuild.erofs @@ -1,76 +1,10 @@ #!/usr/bin/python3 -""" -Create a file containing an erofs filesystem named `filename`. - -See https://en.wikipedia.org/wiki/EROFS for details about the -filesystem. - -Buildhost commands used: `mkfs.erofs` -""" - import os import subprocess import sys import osbuild.api -SCHEMA_2 = """ -"options": { - "additionalProperties": false, - "required": ["filename"], - "properties": { - "filename": { - "description": "Filename for the output", - "type": "string" - }, - "compression": { - "type": "object", - "additionalProperties": false, - "required": ["method"], - "properties": { - "method": { - "description": "Compression method", - "enum": ["lz4", "lz4hc", "lzma"] - }, - "level": { - "description": "Compression level. Note that different methods support different levels. See mkfs.erofs(1) for more details", - "type": "number" - } - } - }, - "options": { - "description": "Extended options for the filesystem, see mkfs.erofs(1)", - "type": "array", - "minItems": 1, - "items:": { - "enum": [ - "all-fragments", - "dedupe", - "force-inode-compact", - "force-inode-extended", - "force-inode-blockmap", - "force-chunk-indexes", - "fragments", - "noinline_data", - "ztailpacking" - ] - } - } - } -}, -"inputs": { - "type": "object", - "additionalProperties": false, - "required": ["tree"], - "properties": { - "tree": { - "type": "object", - "additionalProperties": true - } - } -} -""" - def main(inputs, output_dir, options): source = inputs["tree"]["path"] diff --git a/stages/org.osbuild.erofs.meta.json b/stages/org.osbuild.erofs.meta.json new file mode 100644 index 00000000..fcd10ab7 --- /dev/null +++ b/stages/org.osbuild.erofs.meta.json @@ -0,0 +1,74 @@ +{ + "summary": "Create a file containing an erofs filesystem named `filename`.", + "description": [ + "See https://en.wikipedia.org/wiki/EROFS for details about the", + "filesystem.", + "Buildhost commands used: `mkfs.erofs`" + ], + "schema_2": { + "options": { + "additionalProperties": false, + "required": [ + "filename" + ], + "properties": { + "filename": { + "description": "Filename for the output", + "type": "string" + }, + "compression": { + "type": "object", + "additionalProperties": false, + "required": [ + "method" + ], + "properties": { + "method": { + "description": "Compression method", + "enum": [ + "lz4", + "lz4hc", + "lzma" + ] + }, + "level": { + "description": "Compression level. Note that different methods support different levels. See mkfs.erofs(1) for more details", + "type": "number" + } + } + }, + "options": { + "description": "Extended options for the filesystem, see mkfs.erofs(1)", + "type": "array", + "minItems": 1, + "items:": { + "enum": [ + "all-fragments", + "dedupe", + "force-inode-compact", + "force-inode-extended", + "force-inode-blockmap", + "force-chunk-indexes", + "fragments", + "noinline_data", + "ztailpacking" + ] + } + } + } + }, + "inputs": { + "type": "object", + "additionalProperties": false, + "required": [ + "tree" + ], + "properties": { + "tree": { + "type": "object", + "additionalProperties": true + } + } + } + } +} diff --git a/stages/org.osbuild.error b/stages/org.osbuild.error index 22e5f8d8..39f30ae2 100755 --- a/stages/org.osbuild.error +++ b/stages/org.osbuild.error @@ -1,27 +1,8 @@ #!/usr/bin/python3 -""" -Return an error - -Error stage. Return the given error. Useful for testing, debugging, and -wasting time. -""" - - import sys import osbuild.api -SCHEMA = """ -"additionalProperties": false, -"properties": { - "returncode": { - "description": "What to return code to use", - "type": "number", - "default": 255 - } -} -""" - def main(_tree, options): errno = options.get("returncode", 255) diff --git a/stages/org.osbuild.error.meta.json b/stages/org.osbuild.error.meta.json new file mode 100644 index 00000000..78018b39 --- /dev/null +++ b/stages/org.osbuild.error.meta.json @@ -0,0 +1,17 @@ +{ + "summary": "Return an error", + "description": [ + "Error stage. Return the given error. Useful for testing, debugging, and", + "wasting time." + ], + "schema": { + "additionalProperties": false, + "properties": { + "returncode": { + "description": "What to return code to use", + "type": "number", + "default": 255 + } + } + } +} diff --git a/stages/org.osbuild.experimental.ostree.config b/stages/org.osbuild.experimental.ostree.config index 5b8bec63..30ae6194 100755 --- a/stages/org.osbuild.experimental.ostree.config +++ b/stages/org.osbuild.experimental.ostree.config @@ -1,52 +1,10 @@ #!/usr/bin/python3 -""" -Change OSTree configuration experimental options - -NOTE: This stage is experimental and subject to changes - -Change the configuration for an OSTree repository. -Currently only the following values are supported: - - `integrity.composefs` - -See `ostree.repo-config(5)` for more information. -""" - import os import sys import osbuild.api from osbuild.util import ostree -SCHEMA = """ -"additionalProperties": false, -"required": ["repo"], -"properties": { - "repo": { - "description": "Location of the OSTree repo.", - "type": "string" - }, - "config": { - "type": "object", - "additionalProperties": false, - "description": "OSTree configuration groups", - "properties": { - "integrity": { - "type": "object", - "additionalProperties": false, - "description": "Options concerning the sysroot", - "properties": { - "composefs": { - "description": "Enable composefs image generation on deploy.", - "type": "string", - "enum": ["true", "false", "maybe"] - } - } - } - } - } -} -""" - def main(tree, options): repo = os.path.join(tree, options["repo"].lstrip("/")) diff --git a/stages/org.osbuild.experimental.ostree.config.meta.json b/stages/org.osbuild.experimental.ostree.config.meta.json new file mode 100644 index 00000000..f65054ac --- /dev/null +++ b/stages/org.osbuild.experimental.ostree.config.meta.json @@ -0,0 +1,45 @@ +{ + "summary": "Change OSTree configuration experimental options", + "description": [ + "NOTE: This stage is experimental and subject to changes", + "Change the configuration for an OSTree repository.", + "Currently only the following values are supported:", + " - `integrity.composefs`", + "See `ostree.repo-config(5)` for more information." + ], + "schema": { + "additionalProperties": false, + "required": [ + "repo" + ], + "properties": { + "repo": { + "description": "Location of the OSTree repo.", + "type": "string" + }, + "config": { + "type": "object", + "additionalProperties": false, + "description": "OSTree configuration groups", + "properties": { + "integrity": { + "type": "object", + "additionalProperties": false, + "description": "Options concerning the sysroot", + "properties": { + "composefs": { + "description": "Enable composefs image generation on deploy.", + "type": "string", + "enum": [ + "true", + "false", + "maybe" + ] + } + } + } + } + } + } + } +} diff --git a/stages/org.osbuild.fdo b/stages/org.osbuild.fdo index cbfdd342..87453079 100755 --- a/stages/org.osbuild.fdo +++ b/stages/org.osbuild.fdo @@ -1,37 +1,10 @@ #!/usr/bin/python3 -""" -FDO initial DIUN certificates - -FDO stage to write down the initial DIUN pub key root certificates -to be read by the manufacturer client - -This will create a '/fdo_diun_root_certs.pem' with content -specified via the `rootcerts` input. -""" - import os import shutil import sys import osbuild.api -SCHEMA_2 = r""" -"inputs": { - "type": "object", - "additionalProperties": false, - "required": ["rootcerts"], - "properties": { - "rootcerts": { - "type": "object", - "additionalProperties": true - } - } -}, -"options": { - "additionalProperties": false -} -""" - def parse_input(inputs): image = inputs["rootcerts"] diff --git a/stages/org.osbuild.fdo.meta.json b/stages/org.osbuild.fdo.meta.json new file mode 100644 index 00000000..cd5fb259 --- /dev/null +++ b/stages/org.osbuild.fdo.meta.json @@ -0,0 +1,27 @@ +{ + "summary": "FDO initial DIUN certificates", + "description": [ + "FDO stage to write down the initial DIUN pub key root certificates", + "to be read by the manufacturer client", + "This will create a '/fdo_diun_root_certs.pem' with content", + "specified via the `rootcerts` input." + ], + "schema_2": { + "inputs": { + "type": "object", + "additionalProperties": false, + "required": [ + "rootcerts" + ], + "properties": { + "rootcerts": { + "type": "object", + "additionalProperties": true + } + } + }, + "options": { + "additionalProperties": false + } + } +} diff --git a/stages/org.osbuild.firewall b/stages/org.osbuild.firewall index 5b7611b9..0f71b832 100755 --- a/stages/org.osbuild.firewall +++ b/stages/org.osbuild.firewall @@ -1,98 +1,9 @@ #!/usr/bin/python3 -""" -Configure firewall - -Configure firewalld using the `firewall-offline-cmd` from inside the target. - -This stage adds each of the given `ports` and `enabled_services` to the default -firewall zone using the `--port` and `--service` options, then removes the -services listed in `disabled_services` with `--remove-service`. - -Ports should be specified as "portid:protocol" or "portid-portid:protocol", -where "portid" is a number (or a port name from `/etc/services`, like "ssh" or -"echo") and "protocol" is one of "tcp", "udp", "sctp", or "dccp". - -Enabling or disabling a service that is already enabled or disabled will not -cause an error. - -Attempting to enable/disable an unknown service name will cause this stage to -fail. Known service names are determined by the contents of firewalld's -configuration directories, usually `/{lib,etc}/firewalld/services/*.xml`, and -may vary from release to release. - -WARNING: this stage uses `chroot` to run `firewall-offline-cmd` inside the -target tree, which means it may fail unexpectedly when the buildhost and target -are different arches or OSes. -""" - - import subprocess import sys import osbuild.api -SCHEMA = """ -"additionalProperties": false, -"properties": { - "ports": { - "description": "Ports (or port ranges) to open", - "type": "array", - "items": { - "type": "string", - "description": "A port or port range: 'portid[-portid]:protocol'", - "pattern": ".:(tcp|udp|sctp|dccp)$" - } - }, - "enabled_services": { - "description": "Network services to allow in the default firewall zone", - "type": "array", - "items": { - "type": "string", - "description": "Service name (from /{lib,etc}/firewalld/services/*.xml)" - } - }, - "disabled_services": { - "description": "Network services to remove from the default firewall zone", - "type": "array", - "items": { - "type": "string", - "description": "Service name (from /{lib,etc}/firewalld/services/*.xml)" - } - }, - "default_zone": { - "description": "Set default zone for connections and interfaces where no zone has been selected.", - "type": "string" - }, - "zones": { - "description": "Bind a list of network sources to a zone to restrict traffic from those sources based on the settings of the zone.", - "type": "array", - "minItems": 1, - "items": { - "additionalProperties": false, - "type": "object", - "description": "configuration for each zone", - "required": ["name", "sources"], - "properties": { - "name": { - "type": "string", - "description": "name of the zone, if left empty the sources will apply to the default zone.", - "pattern": "^[a-zA-Z0-9_-]+$" - }, - "sources": { - "type": "array", - "description": "list of sources for the zone", - "items": { - "additionalProperties": false, - "type": "string", - "description": "A source: [/]||ipset:" - } - } - } - } - } -} -""" - def main(tree, options): # Takes a list of : pairs diff --git a/stages/org.osbuild.firewall.meta.json b/stages/org.osbuild.firewall.meta.json new file mode 100644 index 00000000..782d437a --- /dev/null +++ b/stages/org.osbuild.firewall.meta.json @@ -0,0 +1,85 @@ +{ + "summary": "Configure firewall", + "description": [ + "Configure firewalld using the `firewall-offline-cmd` from inside the target.", + "This stage adds each of the given `ports` and `enabled_services` to the default", + "firewall zone using the `--port` and `--service` options, then removes the", + "services listed in `disabled_services` with `--remove-service`.", + "Ports should be specified as \"portid:protocol\" or \"portid-portid:protocol\",", + "where \"portid\" is a number (or a port name from `/etc/services`, like \"ssh\" or", + "\"echo\") and \"protocol\" is one of \"tcp\", \"udp\", \"sctp\", or \"dccp\".", + "Enabling or disabling a service that is already enabled or disabled will not", + "cause an error.", + "Attempting to enable/disable an unknown service name will cause this stage to", + "fail. Known service names are determined by the contents of firewalld's", + "configuration directories, usually `/{lib,etc}/firewalld/services/*.xml`, and", + "may vary from release to release.", + "WARNING: this stage uses `chroot` to run `firewall-offline-cmd` inside the", + "target tree, which means it may fail unexpectedly when the buildhost and target", + "are different arches or OSes." + ], + "schema": { + "additionalProperties": false, + "properties": { + "ports": { + "description": "Ports (or port ranges) to open", + "type": "array", + "items": { + "type": "string", + "description": "A port or port range: 'portid[-portid]:protocol'", + "pattern": ".:(tcp|udp|sctp|dccp)$" + } + }, + "enabled_services": { + "description": "Network services to allow in the default firewall zone", + "type": "array", + "items": { + "type": "string", + "description": "Service name (from /{lib,etc}/firewalld/services/*.xml)" + } + }, + "disabled_services": { + "description": "Network services to remove from the default firewall zone", + "type": "array", + "items": { + "type": "string", + "description": "Service name (from /{lib,etc}/firewalld/services/*.xml)" + } + }, + "default_zone": { + "description": "Set default zone for connections and interfaces where no zone has been selected.", + "type": "string" + }, + "zones": { + "description": "Bind a list of network sources to a zone to restrict traffic from those sources based on the settings of the zone.", + "type": "array", + "minItems": 1, + "items": { + "additionalProperties": false, + "type": "object", + "description": "configuration for each zone", + "required": [ + "name", + "sources" + ], + "properties": { + "name": { + "type": "string", + "description": "name of the zone, if left empty the sources will apply to the default zone.", + "pattern": "^[a-zA-Z0-9_-]+$" + }, + "sources": { + "type": "array", + "description": "list of sources for the zone", + "items": { + "additionalProperties": false, + "type": "string", + "description": "A source: [/]||ipset:" + } + } + } + } + } + } + } +} diff --git a/stages/org.osbuild.first-boot b/stages/org.osbuild.first-boot index bd6708f5..65946990 100755 --- a/stages/org.osbuild.first-boot +++ b/stages/org.osbuild.first-boot @@ -1,45 +1,9 @@ #!/usr/bin/python3 -""" -Execute commands on first-boot - -Sequentially execute a list of commands on first-boot / instantiation. - -This stage uses a logic similar to systemd's first-boot to execute a given -script only the first time the image is booted. - -An empty flag file /etc/osbuild-first-boot is written to /etc and a systemd -service is enabled that is only run when the file exits, and will remove it -before executing the given commands. - -If the flag-file cannot be removed, the service fails without executing -any further first-boot commands. -""" - - import os import sys import osbuild.api -SCHEMA = """ -"additionalProperties": false, -"required": ["commands"], -"properties": { - "commands": { - "type": "array", - "description": "The command lines to execute", - "items": { - "type": "string" - } - }, - "wait_for_network": { - "type": "boolean", - "description": "Wait for the network to be up before executing", - "default": false - } -} -""" - def add_first_boot(tree, commands, wait_for_network): if wait_for_network: diff --git a/stages/org.osbuild.first-boot.meta.json b/stages/org.osbuild.first-boot.meta.json new file mode 100644 index 00000000..29ed781b --- /dev/null +++ b/stages/org.osbuild.first-boot.meta.json @@ -0,0 +1,33 @@ +{ + "summary": "Execute commands on first-boot", + "description": [ + "Sequentially execute a list of commands on first-boot / instantiation.", + "This stage uses a logic similar to systemd's first-boot to execute a given", + "script only the first time the image is booted.", + "An empty flag file /etc/osbuild-first-boot is written to /etc and a systemd", + "service is enabled that is only run when the file exits, and will remove it", + "before executing the given commands.", + "If the flag-file cannot be removed, the service fails without executing", + "any further first-boot commands." + ], + "schema": { + "additionalProperties": false, + "required": [ + "commands" + ], + "properties": { + "commands": { + "type": "array", + "description": "The command lines to execute", + "items": { + "type": "string" + } + }, + "wait_for_network": { + "type": "boolean", + "description": "Wait for the network to be up before executing", + "default": false + } + } + } +} diff --git a/stages/org.osbuild.fix-bls b/stages/org.osbuild.fix-bls index 784ae2cc..7c4e58a2 100755 --- a/stages/org.osbuild.fix-bls +++ b/stages/org.osbuild.fix-bls @@ -1,40 +1,10 @@ #!/usr/bin/python3 -""" -Fix paths in /boot/loader/entries - -Fixes paths in /boot/loader/entries that have incorrect paths for /boot. - -This happens because some boot loader config tools (e.g. grub2-mkrelpath) -examine /proc/self/mountinfo to find the "real" path to /boot, and find the -path to the osbuild tree - which won't be valid at boot time for this image. - -The paths in the Bootloader Specification are relative to the partition -they are located on, i.e. `/boot/loader/...` if `/boot` is on the root -file-system partition. If `/boot` is on a separate partition, the correct -path would be `/loader/.../` The `prefix` can be used to adjust for that. -By default it is `/boot`, i.e. assumes `/boot` is on the root file-system. - -This stage reads and (re)writes all .conf files in /boot/loader/entries. -""" - - import glob import re import sys import osbuild.api -SCHEMA = """ -"additionalProperties": false, -"properties": { - "prefix": { - "description": "Prefix to use, normally `/boot`", - "type": "string", - "default": "/boot" - } -} -""" - def main(tree, options): """Fix broken paths in /boot/loader/entries. diff --git a/stages/org.osbuild.fix-bls.meta.json b/stages/org.osbuild.fix-bls.meta.json new file mode 100644 index 00000000..e56ebd16 --- /dev/null +++ b/stages/org.osbuild.fix-bls.meta.json @@ -0,0 +1,25 @@ +{ + "summary": "Fix paths in /boot/loader/entries", + "description": [ + "Fixes paths in /boot/loader/entries that have incorrect paths for /boot.", + "This happens because some boot loader config tools (e.g. grub2-mkrelpath)", + "examine /proc/self/mountinfo to find the \"real\" path to /boot, and find the", + "path to the osbuild tree - which won't be valid at boot time for this image.", + "The paths in the Bootloader Specification are relative to the partition", + "they are located on, i.e. `/boot/loader/...` if `/boot` is on the root", + "file-system partition. If `/boot` is on a separate partition, the correct", + "path would be `/loader/.../` The `prefix` can be used to adjust for that.", + "By default it is `/boot`, i.e. assumes `/boot` is on the root file-system.", + "This stage reads and (re)writes all .conf files in /boot/loader/entries." + ], + "schema": { + "additionalProperties": false, + "properties": { + "prefix": { + "description": "Prefix to use, normally `/boot`", + "type": "string", + "default": "/boot" + } + } + } +} diff --git a/stages/org.osbuild.fstab b/stages/org.osbuild.fstab index a9af5ffe..8c6659b1 100755 --- a/stages/org.osbuild.fstab +++ b/stages/org.osbuild.fstab @@ -1,138 +1,9 @@ #!/usr/bin/python3 -""" -Create /etc/fstab entries for filesystems - -Each filesystem item must have at least the fs_spec, i.e `uuid`, -`label`, `partlabel` or `device` and a `path` (mount point). - -This stage replaces /etc/fstab, removing any existing entries. - -NB: The ostree configuration options are experimental and might -be replaced with a different mechanism in the near future. -""" - - import sys import osbuild.api from osbuild.util import ostree -SCHEMA = """ -"additionalProperties": false, -"required": ["filesystems"], -"properties": { - "ostree": { - "type": "object", - "additionalProperties": false, - "required": ["deployment"], - "properties": { - "deployment": { - "type": "object", - "additionalProperties": false, - "oneOf": [ - { - "properties": { - "default": {"enum": [false]} - }, - "required": ["osname", "ref"] - }, - { - "properties": { - "default": {"enum": [true]} - }, - "not": { - "anyOf": [ - {"required": ["osname"]}, - {"required": ["ref"]}, - {"required": ["serial"]} - ] - } - } - ], - "properties": { - "osname": { - "description": "Name of the stateroot to be used in the deployment", - "type": "string" - }, - "ref": { - "description": "OStree ref to create and use for deployment", - "type": "string" - }, - "serial": { - "description": "The deployment serial (usually '0')", - "type": "number", - "default": 0 - }, - "default": { - "description": "Find and use the default ostree deployment", - "type": "boolean", - "default": false - } - } - } - } - }, - "filesystems": { - "type": "array", - "description": "array of filesystem objects", - "items": { - "type": "object", - "oneOf": [{ - "required": ["device", "path"] - }, { - "required": ["uuid", "path"] - }, { - "required": ["label", "path"] - }, { - "required": ["partlabel", "path"] - }], - "properties": { - "device": { - "description": "Device node", - "type": "string" - }, - "uuid": { - "description": "Filesystem UUID", - "type": "string" - }, - "label": { - "description": "Filesystem label", - "type": "string" - }, - "partlabel": { - "description": "Partition label.", - "type": "string" - }, - "path": { - "description": "Filesystem mountpoint", - "type": "string" - }, - "vfs_type": { - "description": "Filesystem type", - "type": "string", - "default": "none" - }, - "options": { - "description": "Filesystem options (comma-separated)", - "type": "string", - "default": "defaults" - }, - "freq": { - "description": "dump(8) period in days", - "type": "number", - "default": 0 - }, - "passno": { - "description": "pass number on parallel fsck(8)", - "type": "number", - "default": 0 - } - } - } - } -} -""" - def main(tree, options): filesystems = options["filesystems"] diff --git a/stages/org.osbuild.fstab.meta.json b/stages/org.osbuild.fstab.meta.json new file mode 100644 index 00000000..55c7256d --- /dev/null +++ b/stages/org.osbuild.fstab.meta.json @@ -0,0 +1,169 @@ +{ + "summary": "Create /etc/fstab entries for filesystems", + "description": [ + "Each filesystem item must have at least the fs_spec, i.e `uuid`,", + "`label`, `partlabel` or `device` and a `path` (mount point).", + "This stage replaces /etc/fstab, removing any existing entries.", + "NB: The ostree configuration options are experimental and might", + "be replaced with a different mechanism in the near future." + ], + "schema": { + "additionalProperties": false, + "required": [ + "filesystems" + ], + "properties": { + "ostree": { + "type": "object", + "additionalProperties": false, + "required": [ + "deployment" + ], + "properties": { + "deployment": { + "type": "object", + "additionalProperties": false, + "oneOf": [ + { + "properties": { + "default": { + "enum": [ + false + ] + } + }, + "required": [ + "osname", + "ref" + ] + }, + { + "properties": { + "default": { + "enum": [ + true + ] + } + }, + "not": { + "anyOf": [ + { + "required": [ + "osname" + ] + }, + { + "required": [ + "ref" + ] + }, + { + "required": [ + "serial" + ] + } + ] + } + } + ], + "properties": { + "osname": { + "description": "Name of the stateroot to be used in the deployment", + "type": "string" + }, + "ref": { + "description": "OStree ref to create and use for deployment", + "type": "string" + }, + "serial": { + "description": "The deployment serial (usually '0')", + "type": "number", + "default": 0 + }, + "default": { + "description": "Find and use the default ostree deployment", + "type": "boolean", + "default": false + } + } + } + } + }, + "filesystems": { + "type": "array", + "description": "array of filesystem objects", + "items": { + "type": "object", + "oneOf": [ + { + "required": [ + "device", + "path" + ] + }, + { + "required": [ + "uuid", + "path" + ] + }, + { + "required": [ + "label", + "path" + ] + }, + { + "required": [ + "partlabel", + "path" + ] + } + ], + "properties": { + "device": { + "description": "Device node", + "type": "string" + }, + "uuid": { + "description": "Filesystem UUID", + "type": "string" + }, + "label": { + "description": "Filesystem label", + "type": "string" + }, + "partlabel": { + "description": "Partition label.", + "type": "string" + }, + "path": { + "description": "Filesystem mountpoint", + "type": "string" + }, + "vfs_type": { + "description": "Filesystem type", + "type": "string", + "default": "none" + }, + "options": { + "description": "Filesystem options (comma-separated)", + "type": "string", + "default": "defaults" + }, + "freq": { + "description": "dump(8) period in days", + "type": "number", + "default": 0 + }, + "passno": { + "description": "pass number on parallel fsck(8)", + "type": "number", + "default": 0 + } + } + } + } + } + } +} diff --git a/stages/org.osbuild.gcp.guest-agent.conf b/stages/org.osbuild.gcp.guest-agent.conf index 8e9dedb8..f340a0de 100755 --- a/stages/org.osbuild.gcp.guest-agent.conf +++ b/stages/org.osbuild.gcp.guest-agent.conf @@ -1,16 +1,4 @@ #!/usr/bin/python3 -""" -Create or modify the GCP guest-agent config - -Create or modify the GCP guest-agent config, depending on the -scope either at: - /etc/default/instance_configs.cfg.distro or - /etc/default/instance_configs.cfg - -Configuration sections and options may contain any of these values: -https://github.com/GoogleCloudPlatform/guest-agent#configuration -""" - import os import sys @@ -18,204 +6,6 @@ import iniparse import osbuild.api -SCHEMA = r""" -"definitions": { - "Accounts": { - "type": "object", - "additionalProperties": false, - "description": "Accounts section.", - "minProperties": 1, - "properties": { - "deprovision_remove": { - "type": "boolean", - "description": "Makes deprovisioning a user destructive." - }, - "groups": { - "type": "array", - "description": "List of groups for newly provisioned users." - }, - "useradd_cmd": { - "type": "string", - "description": "Command string to create a new user." - }, - "userdel_cmd": { - "type": "string", - "description": "Command string to delete a user." - }, - "usermod_cmd": { - "type": "string", - "description": "Command string to modify a user's groups." - }, - "gpasswd_add_cmd": { - "type": "string", - "description": "Command string to add a user to a group." - }, - "gpasswd_remove_cmd": { - "type": "string", - "description": "Command string to remove a user from a group." - }, - "groupadd_cmd": { - "type": "string", - "description": "Command string to create a new group." - } - } - }, - "Daemons": { - "type": "object", - "additionalProperties": false, - "description": "Daemons section.", - "minProperties": 1, - "properties": { - "accounts_daemon": { - "type": "boolean", - "description": "Disables the accounts daemon." - }, - "clock_skew_daemon": { - "type": "boolean", - "description": "Disables the clock skew daemon." - }, - "network_daemon": { - "type": "boolean", - "description": "Disables the network daemon." - } - } - }, - "InstanceSetup": { - "type": "object", - "additionalProperties": false, - "description": "InstanceSetup section.", - "minProperties": 1, - "properties": { - "host_key_types": { - "type": "array", - "description": "List of host key types to generate." - }, - "optimize_local_ssd": { - "type": "boolean", - "description": "Prevents optimizing for local SSD." - }, - "network_enabled": { - "type": "boolean", - "description": "Skips instance setup functions that require metadata." - }, - "set_boto_config": { - "type": "boolean", - "description": "Skip setting up a boto config." - }, - "set_host_keys": { - "type": "boolean", - "description": "Skips generating host keys on first boot." - }, - "set_multiqueue": { - "type": "boolean", - "description": "Skips multiqueue driver support." - } - } - }, - "IpForwarding": { - "type": "object", - "additionalProperties": false, - "description": "IpForwarding section.", - "minProperties": 1, - "properties": { - "ethernet_proto_id": { - "type": "string", - "description": "Protocol ID string for daemon added routes." - }, - "ip_aliases": { - "type": "boolean", - "description": "Disables setting up alias IP routes." - }, - "target_instance_ips": { - "type": "boolean", - "description": "Disables internal IP address load balancing." - } - } - }, - "MetadataScripts": { - "type": "object", - "additionalProperties": false, - "description": "MetadataScripts section.", - "minProperties": 1, - "properties": { - "default_shell": { - "type": "string", - "description": "String with the default shell to execute scripts." - }, - "run_dir": { - "type": "string", - "description": "String base directory where metadata scripts are executed." - }, - "startup": { - "type": "boolean", - "description": "Disables startup script execution." - }, - "shutdown": { - "type": "boolean", - "description": "Disables shutdown script execution." - } - } - }, - "NetworkInterfaces": { - "type": "object", - "additionalProperties": false, - "description": "NetworkInterfaces section.", - "minProperties": 1, - "properties": { - "setup": { - "type": "boolean", - "description": "Skips network interface setup." - }, - "ip_forwarding": { - "type": "boolean", - "description": "Skips IP forwarding." - }, - "dhcp_command": { - "type": "string", - "description": "Path for alternate dhcp executable used to enable network interfaces." - } - } - } -}, -"additionalProperties": false, -"required": ["config"], -"description": "Configure GCP guest-agent.", -"properties": { - "config_scope": { - "type": "string", - "description": "Create distro-wide or instance-specific configuration.", - "enum": ["distro", "instance"], - "default": "distro" - }, - "config": { - "type": "object", - "additionalProperties": false, - "description": "GCP guest-agent configuration.", - "minProperties": 1, - "properties": { - "Accounts": { - "$ref": "#/definitions/Accounts" - }, - "Daemons": { - "$ref": "#/definitions/Daemons" - }, - "InstanceSetup": { - "$ref": "#/definitions/InstanceSetup" - }, - "IpForwarding": { - "$ref": "#/definitions/IpForwarding" - }, - "MetadataScripts": { - "$ref": "#/definitions/MetadataScripts" - }, - "NetworkInterfaces": { - "$ref": "#/definitions/NetworkInterfaces" - } - } - } -} -""" - def option_value_to_str(value): """ diff --git a/stages/org.osbuild.gcp.guest-agent.conf.meta.json b/stages/org.osbuild.gcp.guest-agent.conf.meta.json new file mode 100644 index 00000000..0c9f618a --- /dev/null +++ b/stages/org.osbuild.gcp.guest-agent.conf.meta.json @@ -0,0 +1,213 @@ +{ + "summary": "Create or modify the GCP guest-agent config", + "description": [ + "Create or modify the GCP guest-agent config, depending on the", + "scope either at:", + " /etc/default/instance_configs.cfg.distro or", + " /etc/default/instance_configs.cfg", + "Configuration sections and options may contain any of these values:", + "https://github.com/GoogleCloudPlatform/guest-agent#configuration" + ], + "schema": { + "definitions": { + "Accounts": { + "type": "object", + "additionalProperties": false, + "description": "Accounts section.", + "minProperties": 1, + "properties": { + "deprovision_remove": { + "type": "boolean", + "description": "Makes deprovisioning a user destructive." + }, + "groups": { + "type": "array", + "description": "List of groups for newly provisioned users." + }, + "useradd_cmd": { + "type": "string", + "description": "Command string to create a new user." + }, + "userdel_cmd": { + "type": "string", + "description": "Command string to delete a user." + }, + "usermod_cmd": { + "type": "string", + "description": "Command string to modify a user's groups." + }, + "gpasswd_add_cmd": { + "type": "string", + "description": "Command string to add a user to a group." + }, + "gpasswd_remove_cmd": { + "type": "string", + "description": "Command string to remove a user from a group." + }, + "groupadd_cmd": { + "type": "string", + "description": "Command string to create a new group." + } + } + }, + "Daemons": { + "type": "object", + "additionalProperties": false, + "description": "Daemons section.", + "minProperties": 1, + "properties": { + "accounts_daemon": { + "type": "boolean", + "description": "Disables the accounts daemon." + }, + "clock_skew_daemon": { + "type": "boolean", + "description": "Disables the clock skew daemon." + }, + "network_daemon": { + "type": "boolean", + "description": "Disables the network daemon." + } + } + }, + "InstanceSetup": { + "type": "object", + "additionalProperties": false, + "description": "InstanceSetup section.", + "minProperties": 1, + "properties": { + "host_key_types": { + "type": "array", + "description": "List of host key types to generate." + }, + "optimize_local_ssd": { + "type": "boolean", + "description": "Prevents optimizing for local SSD." + }, + "network_enabled": { + "type": "boolean", + "description": "Skips instance setup functions that require metadata." + }, + "set_boto_config": { + "type": "boolean", + "description": "Skip setting up a boto config." + }, + "set_host_keys": { + "type": "boolean", + "description": "Skips generating host keys on first boot." + }, + "set_multiqueue": { + "type": "boolean", + "description": "Skips multiqueue driver support." + } + } + }, + "IpForwarding": { + "type": "object", + "additionalProperties": false, + "description": "IpForwarding section.", + "minProperties": 1, + "properties": { + "ethernet_proto_id": { + "type": "string", + "description": "Protocol ID string for daemon added routes." + }, + "ip_aliases": { + "type": "boolean", + "description": "Disables setting up alias IP routes." + }, + "target_instance_ips": { + "type": "boolean", + "description": "Disables internal IP address load balancing." + } + } + }, + "MetadataScripts": { + "type": "object", + "additionalProperties": false, + "description": "MetadataScripts section.", + "minProperties": 1, + "properties": { + "default_shell": { + "type": "string", + "description": "String with the default shell to execute scripts." + }, + "run_dir": { + "type": "string", + "description": "String base directory where metadata scripts are executed." + }, + "startup": { + "type": "boolean", + "description": "Disables startup script execution." + }, + "shutdown": { + "type": "boolean", + "description": "Disables shutdown script execution." + } + } + }, + "NetworkInterfaces": { + "type": "object", + "additionalProperties": false, + "description": "NetworkInterfaces section.", + "minProperties": 1, + "properties": { + "setup": { + "type": "boolean", + "description": "Skips network interface setup." + }, + "ip_forwarding": { + "type": "boolean", + "description": "Skips IP forwarding." + }, + "dhcp_command": { + "type": "string", + "description": "Path for alternate dhcp executable used to enable network interfaces." + } + } + } + }, + "additionalProperties": false, + "required": [ + "config" + ], + "description": "Configure GCP guest-agent.", + "properties": { + "config_scope": { + "type": "string", + "description": "Create distro-wide or instance-specific configuration.", + "enum": [ + "distro", + "instance" + ], + "default": "distro" + }, + "config": { + "type": "object", + "additionalProperties": false, + "description": "GCP guest-agent configuration.", + "minProperties": 1, + "properties": { + "Accounts": { + "$ref": "#/definitions/Accounts" + }, + "Daemons": { + "$ref": "#/definitions/Daemons" + }, + "InstanceSetup": { + "$ref": "#/definitions/InstanceSetup" + }, + "IpForwarding": { + "$ref": "#/definitions/IpForwarding" + }, + "MetadataScripts": { + "$ref": "#/definitions/MetadataScripts" + }, + "NetworkInterfaces": { + "$ref": "#/definitions/NetworkInterfaces" + } + } + } + } + } +} diff --git a/stages/org.osbuild.greenboot b/stages/org.osbuild.greenboot index 2aaa63b2..e7409e07 100755 --- a/stages/org.osbuild.greenboot +++ b/stages/org.osbuild.greenboot @@ -1,35 +1,9 @@ #!/usr/bin/python3 -""" -Configure greenboot - -Update configuration of greenboot in /etc/greenboot/greenbot.conf. -""" - import fileinput import sys import osbuild.api -SCHEMA = """ -"additionalProperties": false, -"required": ["config"], -"properties": { - "config": { - "additionalProperties": false, - "description": "greenboot config options", - "type": "object", - "properties": { - "monitor_services": { - "type": "array", - "items": { - "type": "string" - } - } - } - } -} -""" - def main(tree, options): greenboot_conf = options.get("config", {}) diff --git a/stages/org.osbuild.greenboot.meta.json b/stages/org.osbuild.greenboot.meta.json new file mode 100644 index 00000000..a8290dc9 --- /dev/null +++ b/stages/org.osbuild.greenboot.meta.json @@ -0,0 +1,27 @@ +{ + "summary": "Configure greenboot", + "description": [ + "Update configuration of greenboot in /etc/greenboot/greenbot.conf." + ], + "schema": { + "additionalProperties": false, + "required": [ + "config" + ], + "properties": { + "config": { + "additionalProperties": false, + "description": "greenboot config options", + "type": "object", + "properties": { + "monitor_services": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + } +} diff --git a/stages/org.osbuild.groups b/stages/org.osbuild.groups index 42d41c30..07ba4510 100755 --- a/stages/org.osbuild.groups +++ b/stages/org.osbuild.groups @@ -1,43 +1,9 @@ #!/usr/bin/python3 -""" -Create group accounts - -Create group accounts, optionally assigning them static GIDs. - -Runs `groupadd` from the buildhost to create the groups listed in `groups`. -If no `gid` is given, `groupadd` will choose one. - -If the specified group name or GID is already in use, this stage will fail. -""" - - import subprocess import sys import osbuild.api -SCHEMA = """ -"additionalProperties": false, -"properties": { - "groups": { - "type": "object", - "additionalProperties": false, - "description": "Keys are group names, values are objects with group info", - "patternProperties": { - "^[A-Za-z0-9_][A-Za-z0-9_-]{0,31}$": { - "type": "object", - "properties": { - "gid": { - "type": "number", - "description": "GID for this group" - } - } - } - } - } -} -""" - def groupadd(root, name, gid=None): arguments = [] diff --git a/stages/org.osbuild.groups.meta.json b/stages/org.osbuild.groups.meta.json new file mode 100644 index 00000000..367adfb9 --- /dev/null +++ b/stages/org.osbuild.groups.meta.json @@ -0,0 +1,30 @@ +{ + "summary": "Create group accounts", + "description": [ + "Create group accounts, optionally assigning them static GIDs.", + "Runs `groupadd` from the buildhost to create the groups listed in `groups`.", + "If no `gid` is given, `groupadd` will choose one.", + "If the specified group name or GID is already in use, this stage will fail." + ], + "schema": { + "additionalProperties": false, + "properties": { + "groups": { + "type": "object", + "additionalProperties": false, + "description": "Keys are group names, values are objects with group info", + "patternProperties": { + "^[A-Za-z0-9_][A-Za-z0-9_-]{0,31}$": { + "type": "object", + "properties": { + "gid": { + "type": "number", + "description": "GID for this group" + } + } + } + } + } + } + } +} diff --git a/stages/org.osbuild.grub2 b/stages/org.osbuild.grub2 index 5fb784fe..c6effdb1 100755 --- a/stages/org.osbuild.grub2 +++ b/stages/org.osbuild.grub2 @@ -1,80 +1,4 @@ #!/usr/bin/python3 -""" -Configure GRUB2 bootloader and set boot options - -Configure the system to use GRUB2 as the bootloader, and set boot options. - -Sets the GRUB2 boot/root filesystem to `rootfs`. If a separated boot -partition is used it can be specified via `bootfs`. The file-systems -can be identified either via uuid (`{"uuid": ""}`) or label -(`{"label": "