Commit graph

61 commits

Author SHA1 Message Date
Brian C. Lane
28e74f6c9b Add support for using librepo to download packages
Using a metalink or mirrorlist along with the package paths and
checksums allows them to be reliably downloaded even when mirrors are
not all in sync. It will retry with a new mirror until it succeeds, or
has tried all of the mirrors.
2025-01-14 08:19:16 +01:00
Simon de Vlieger
8429acf7e3 test: metadata in describe
Michael Vogt pointed out that testcases start failing when we describe
the new format. Let's add a test case and fix the describe to include
the metadata.

Metadata is freeform in the `Manifest` instance but it is stored on it
during loading (at which time its properties are validated) and returned
as-is on describe.

Signed-off-by: Simon de Vlieger <supakeen@redhat.com>
2024-10-29 08:24:33 +01:00
Michael Vogt
827b238764 format/v2: add new "partition" field to "describe_mount" 2023-12-22 10:18:29 -05:00
Dusty Mabe
ce8408a9c6 mounts: support mounting partitions
This allows us to map in a whole disk as a loopback device with parition
scanning rather than slicing up the disk and creating several loopback
devices. Something like this:

```
      - type: org.osbuild.copy
        inputs:
          tree:
            type: org.osbuild.tree
            origin: org.osbuild.pipeline
            references:
              - name:tree
        options:
          paths:
            - from: input://tree/
              to: mount://root/
        devices:
          efi:
            type: org.osbuild.loopback
            options:
              filename: disk.img
              start:
                mpp-format-int: '{image.layout[''EFI-SYSTEM''].start}'
              size:
                mpp-format-int: '{image.layout[''EFI-SYSTEM''].size}'
          boot:
            type: org.osbuild.loopback
            options:
              filename: disk.img
              start:
                mpp-format-int: '{image.layout[''boot''].start}'
              size:
                mpp-format-int: '{image.layout[''boot''].size}'
          root:
            type: org.osbuild.loopback
            options:
              filename: disk.img
              start:
                mpp-format-int: '{image.layout[''root''].start}'
              size:
                mpp-format-int: '{image.layout[''root''].size}'
        mounts:
          - name: root
            type: org.osbuild.xfs
            source: root
            target: /
          - name: boot
            type: org.osbuild.ext4
            source: boot
            target: /boot
          - name: efi
            type: org.osbuild.fat
            source: efi
            target: /boot/efi
```

now becomes a little more simple:

```
      - type: org.osbuild.copy
        inputs:
          tree:
            type: org.osbuild.tree
            origin: org.osbuild.pipeline
            references:
              - name:tree
        options:
          paths:
            - from: input://tree/
              to: mount://root/
        devices:
          disk:
            type: org.osbuild.loopback
            options:
              filename: disk.img
              partscan: true
        mounts:
          - name: root
            type: org.osbuild.xfs
            source: disk
            partition:
              mpp-format-int: '{image.layout[''root''].partnum}'
            target: /
          - name: boot
            type: org.osbuild.ext4
            source: disk
            partition:
              mpp-format-int: '{image.layout[''boot''].partnum}'
            target: /boot
          - name: efi
            type: org.osbuild.fat
            source: disk
            partition:
              mpp-format-int: '{image.layout[''EFI-SYSTEM''].partnum}'
            target: /boot/efi
```

Fixes https://github.com/osbuild/osbuild/issues/1495
2023-12-22 10:18:29 -05:00
Simon de Vlieger
d60690ce46 tox: add tox
`tox` is a standard testing tool for Python projects, this allows you to
test locally with all your installed Python version with the following
command:

`tox -m test -p all`

To run the tests in parallel for all supported Python versions.

To run linters or type analysis:

```
tox -m lint -p all
tox -m type -p all
```

This commit *also* disables the `import-error` warning from `pylint`,
not all Python versions have the system-installed Python libraries
available and they can't be fetched from PyPI.

Some linters have been added and the general order linters run in has
been changed. This allows for quicker test failure when running
`tox -m lint`. As a consequence the `test_pylint` test has been removed
as it's role can now be fulfilled by `tox`.

Other assorted linter fixes due to newer versions:
- use a str.join method (`consider-using-join`)
- fix various (newer) mypy and pylint issues
- comments starting with `#` and no space due to `autopep8`

This also changes our CI to use the new `tox` setup and on top of that
pins the versions of linters used. This might move into separate
requirements.txt files later on to allow for easier updating of those
dependencies.
2023-08-01 15:01:13 +02:00
Christian Kellner
4b94769f6b format: read metadata from object not result
Now that metadata is stored and can be accessed via `Object.meta`,
read it from the built or stored objects when serializing the
result in the `format.output` functions.
2022-12-09 12:03:40 +01:00
Christian Kellner
baa547b5e9 fmt/v2: extract metadata gathering into function
Extract the piece of code that gathers the metadata from the
result struct into its own (nested) method. It is easier to
read but also prepares for a future change where we read the
metadata from the store instead of the result dict.
2022-12-09 12:03:40 +01:00
Christian Kellner
5bdc8d030c osbuild: auto-detect best available runner
Use the new `Index.detect_runner` method that will give us the best
available runner for a requested one. To do so a new `pipeline.Runner`
class is introduced that stores the `meta.RunnerInfo` class for the
specific runner and the original name that was requested.
In the manifest loading and describing functions of the formats, use
`Index.detect_runner` to get the `RunnerInfo` for a requested runner
and then wrap it in a `pipeline.Runner` object, which is then passed
to the `Manifest.add_pipeline` method.
See also commit "meta: ability to auto-detect runner".
Adjust all test.
2022-10-11 12:49:16 +02:00
Simon de Vlieger
ea6085fae6 osbuild: run isort on all files 2022-09-12 13:32:51 +02:00
Simon de Vlieger
3fd864e5a9 osbuild: fix optional-types
Optional types were provided in places but were not always correct. Add
mypy checking and fix those that fail(ed).
2022-07-13 17:31:37 +02:00
Christian Kellner
3ab2ddd481 pipeline, fmt: use build result object internally
Instead of serializing the `BuildResult` to a dict in `build_stages`,
we keep the object and then only serialize it in the corresponding
formatting code. This doubles down on the separation between the
internal data structures and the external representation of them. It
was partially already done in the v2 format which hand-picked which
elements of the BuildResult it would return for each stage.
2022-06-14 00:15:51 +01:00
Christian Kellner
99abc1373d inputs: support array of objects references
This extends the possible ways of passing references to inputs. The
current ways possible are:
 1) "plain references", an array of strings:
    ["ref1", "ref2", ...]
 2) "object references", a mapping of keys to objects:
    {"ref1": { <options> }, "ref2": { <options> }, ...}

This patch adds a new way:
  3) "array of object references":
    [{"id": "ref1", "options": { ... }}, {"id": ... }, ]

While osbuild promises to preserves the order for "object references"
not all JSON serialization libraries preserve the order since the
JSON specification does leave this up to the implementation.

The new "array of object references" thus allows for specifying the
references together with reference specific options and this in a
specific order.

Additionally this paves the way for specifying the same input twice,
e.g. in the case of the `org.osbuild.files` input where a pipeline
could then be specified twice with different files. This needs core
rework though, since internally we use dictionaries right now.
2022-04-21 16:39:58 +02:00
Alexander Larsson
b31c91d671 v2: Add source-epoch key in pipeline declaration and pass to buildroot
If this is set it is passed down to all stages and set as
SOURCE_DATE_EPOCH in the buildroot environment. This implements
the spec at:
  https://reproducible-builds.org/docs/source-date-epoch/
2022-02-09 09:58:49 +01:00
Christian Kellner
29f2a68eeb osbuild: on-demand building of pipelines
Use the new Manifest.depsolve function to only build the pipelines that
were explicitly requested and their dependencies, taking into account
what is already present in the store.
Since now not all pipeline will be built, there wont be a result entry
for all the pipelines, thus the format version 2 result formatting was
changed to not require the pipeline to be present in result set.
2021-12-02 12:51:30 +00:00
Christian Kellner
a2404c9ec9 formats/v1: propagate build pipeline status
When formatting the the result, switch the default to success,
but then properly propagate the status of the build pipeline.
This should ensure that if there are no pipeline results but
a failed build pipeline, the overall status will be 'failed'.
On the other hand, if no pipelines were built, including tree
or build, the overall status will be 'success'.
2021-12-02 12:51:30 +00:00
Christian Kellner
8770bdf10a formats/v1: remove implicit assembler export
When building a version 1 manifest, the assembler would always be
exported, even when not requested via the `--export` command line
option. This was done for backwards compatibility so to not break
tools relying on that behavior. The problem is that support for
this uses a completely different code path and might also now be
confusing behavior. Thus remove the implicit and really only ever
export what was explicitly requested by the caller.
2021-12-02 12:51:30 +00:00
Christian Kellner
e63fa48504 formats/v2: fix describe for mount without source
Commit 5b1cd2b made `source` and `target` for mounts optional, but
the corresponding code in `describe` still assumes that the device
will always be present. Fix this so that source will only be used
if it is set.
2021-11-08 11:26:37 +00:00
Christian Kellner
5b1cd2b1c5 schema/v2: make mount source and target optional
The previous commit gave the individual mounts more control over the
source and target properties. Do not require them at the global
schema but hand the control if they are optional over to the modules.
2021-10-30 15:32:44 +01:00
Christian Kellner
45d0594b1b device: add support for parent devices
This allows device nesting, i.e. one device being opened inside another
one.
2021-08-13 12:20:54 +02:00
Christian Kellner
36a5f9263a formats/v2: better error reporting for validation 2021-08-13 12:20:54 +02:00
Christian Kellner
4d73760dcd formats/v2: fix mount description for source
The mount has a `source` not `device`. It is just called device
internally because for now it is always a device.
2021-07-21 13:28:22 +02:00
Christian Kellner
ae1296e33a formats/v2: mounts are arrays
The order of entries in a dictionary is not specified by the JSON
standard and hard to control when marshalling dictionaries in Go.
Since the order of mounts is important and the wrong order leads
to wrong mount trees change the `mounts` field to an array. This
breaks existing manifests but after careful deliberation it was
concluded that the original schema with mounts as dictionaries
is not something we want to support. Apologies to everyone.

Adjust the schema of the copy and zipl stage accordingly.
2021-07-21 13:28:22 +02:00
Diaa Sami
02ceb02d2a osbuild: Add validation for source references
Validate source references while loading manifests so that a bad
reference would result in a meaningful error message instead of a
hard-to-understand Python exception.
2021-07-20 20:22:27 +02:00
Christian Kellner
5d22a672b4 format/v1: remove now unused get_ids function
This was only used in a test utility method. Its use was replaced
and thus it is now longer needed.
2021-06-30 12:06:30 +02:00
Christian Kellner
367a044453 osbuild: introduce mount host service
Allows stages to access file systems provided by devices.
This makes mount handling transparent to the stages, i.e.
the individual stages do not need any code for different
file system types and the underlying devices.
2021-06-09 18:37:47 +01:00
Christian Kellner
4f211eb0a5 osbuild: introduce device host service
A new host service that provides device functionality to stages.
Since stages run in a container and are restricted from creating
device nodes, all device handling is done in the main osbuild
process. Currently this is done with the help of APIs and RPC,
e.g. `LoopServer`. Device host services on the other hand allow
declaring devices in the manifest itself and then osbuild will
prepare all devices before running the stage. One desired effect
is that it makes device handling transparent to the stages, e.g.
they don't have to know about loopback devices, LVM or LUKS.
Another result is that specific device handling is now modular
like Inputs and Source are and thus moved out of osbuild itself.
2021-06-09 18:37:47 +01:00
Christian Kellner
26b15a062d format/v2: generalize stage module validation
Generalize the code that validates the stage `inputs`, so it can
be used for future extensions of the stage with new sub-modules.
2021-06-09 18:37:47 +01:00
Christian Kellner
869efab578 format/v2: extract stage-level input description
Extract the loop that describes the inputs at the stage level into
its own function. Mostly to keep the describe_stage method slim.
2021-06-09 18:37:47 +01:00
Christian Kellner
6a3b5818ef format/v2: small whitespace fixes
Fix a misaligned bracket.
2021-06-09 18:37:47 +01:00
Christian Kellner
dfd7ff2500 fmt/v1: correctly infer result from assembler
If a pipeline has an assembler and that assembler failed, the
overall status of the build also needs to be marked as failed.
This used to be the case, but a bug got introduced when the
format abstraction code was added.
2021-03-09 21:40:47 +00:00
Christian Kellner
81c8374d3e sources: rename org.osbuild.{files -> curl}
The `org.osbuild.files` source provides files, but might in the
future not be the only one that does. Therefore rename it to
match the internal tool that is being used to fetch the files.
This is done for most other osbuild modules that target tools.

The format v1 loader is adapted to make this change transparent
for users of the v1 format, so we are backwards compatible.

Change the MPP depsolve preprocessor so that for format v2 based
manifest `org.osbuild.curl` source is used. Also rename the
corresponding source test. Adapt the format v2 mod test to use
the curl source.
2021-02-12 19:27:08 +01:00
Christian Kellner
b516c5bf19 formats/v2: map id -> name if with_id is false
In `describe`, if `with_id` is false, reverse map all pipeline ids
to the names.
2021-02-12 15:55:43 +01:00
Christian Kellner
b05b9ba508 formats/v2: support for schema version 2
Add support for format version 2. The laoding fits to the manifest
description schema in `schema/osbuild2.json`. Loading, describing
and validation are fully functional. The `output` method resturns
results in a new format too but is very much work in progress and
quite a hack right now. The output format will definitely change
again.
2021-02-12 15:55:43 +01:00
Christian Kellner
931eac23c3 sources: introduce source items
All sources fetch various types of `items`, the specific nature
of which is dependent on the source type, but they are all
identifyable by a opaque identifier. In order for osbuild to
check that all the inputs that a stage needs are are indeed
contained in the manifest description, osbuild must learn what
ids are fetched by what source. This is done by standarzing
the common "items" part, i.e. the "id" -> "options for that id"
mapping that is common to all sources.
For the version 1 of the format, extract the files and ostree
the item information from the respective options.
Adapt the sources (files, ostree) so that they use the new items
information, but also fall back to the old style; the latter is
needed since the sources tests still uses the SourceServer.
2021-02-10 15:44:24 +01:00
Christian Kellner
3b7141417c formats/v1: extract source loading code
Extract the code that loads individual source into its own
function.
2021-02-10 15:44:24 +01:00
Christian Kellner
8f97c13dda formats/v1: specify format version
Specify the version, i.e. "1", that this format is able to read
and write. Additionally add a proper doc string describing the
format.
2021-02-09 13:08:24 +01:00
Christian Kellner
7ffae5669c osbuild: convert ostree stage to inputs
Convert the `org.osbuild.ostree` stage to use inputs instead of
sources. In the format (version 1) loading code, convert the
stage to use an input based on the existing stage options.
2021-02-06 12:04:30 +01:00
Christian Kellner
0256396270 osbuild: convert rpm stage to use inputs
Convert the `org.osbuild.rpm` stage to use inputs instead of
sources. When loading v1 formats the input is generated from
the stage options.
2021-02-06 12:04:30 +01:00
Christian Kellner
57ccf403e1 formats/v1: use new Stage.add_input
Instead of manually constructing and appending the input for
stages (here the stages that replace the assembler), use the
new `Stage.add_input` method.
2021-02-06 12:04:30 +01:00
Christian Kellner
ba7f6fe7c7 formats/v1: extract stage parsing into function
Extract the code that creates a stage given its description into
its own function.
2021-02-06 12:04:30 +01:00
Christian Kellner
eb1d17d8ac input: add references and origin
Currently all options for inputs are totally opaque to osbuild
itself. This is neat from a seperation of concerns point of view
but has one major downside: osbuild can not verify the integrity
of the pipeline graph, i.e. if all inputs that need pipelines or
sources do indeed exists. Therefore intrdouce two generic fields
for inputs: `origin` and `references`. The former can either be
a source or a pipeline. The latter is an array of identifiers or
a dictionary where the keys are the identifiers and the values
are additional options for that id. The identifiers then refer
to either resources obtained via a source or a pipeline that has
already been built.
2021-02-06 12:04:30 +01:00
Christian Kellner
12c9173faf manifest: use newly introduced Source class
Add a new `add_source` method that will add an individual `Source`
to a `Manifest` give its `ModuleInfo` and options. The dictionary
of source options in the manifest is replaced with a list of such
`Sources` and `add_source` will append to it. Adap the version 1
format code to use `add_source` and reconstruct the source options
from the list of source on `describe`.
Remove the `sources_options` constructor parameter for `Manifest`
and adapt all the source base for this.
2021-02-06 12:04:30 +01:00
Christian Kellner
c6432d0adb pipeline: replace tree_id with id
Now that `Pipelines` have no assemblers anymore and thus only one
identifier, i.e. the one corresponding to the tree (`tree_id`),
the `id` and `tree_id` are now the same. Therefore replace the
usage of `tree_id` with `id` and drop the former. Add some extra
documentation including some caveats about the uniquness of `id`.
2021-01-22 15:03:19 +01:00
Christian Kellner
53e9ec850b osbuild: assemblers are pipelines now
Convert the assembler phase of the main pipeline in the old format
into a new Pipeline that as the assembler as a stage, where the
input of that stage is the main pipeline. This removes the need of
having "assemblers" as special concepts and thus the corresponding
code in `Pipeline` is removed. The new assembler pipeline is marked
as exported, but the pipeline that builds the tree is not anymore.
Adapt the `describe` and `output` functions of the `v1` format to
handle the assembler pipeline. Also change the tests accordingly.

NB: The id reported for the assembler via `--inspect` and the result
will change as a result of this, since the assembler stage is now
the first and only stage of a new pipeline and thus has no base
anymore.
2021-01-22 15:03:19 +01:00
Christian Kellner
569345cc72 pipeline: identify pipelines by name
Every pipeline that gets added to the `Manifest` now need to have
a unique name by which it can be identified. The version 1 format
loader is changed so that the main pipeline that builds the tree
is always called `tree`. The build pipeline for it will be called
`build` and further recursive build pipelines `build-build`, where
the number of repetitions of `build` corresponds to their level of
nesting. An assembler, if it exists, will be added as `assembler`.
The `Manifest.__getitem__` helper is changed so it will first try
to access pipeline via its name and then fall back to an id based
search. NB: in the degenrate case of multiple pipelines that have
exactly the same `id`, i.e. same stages, with the same options and
same build pipeline, only the first one will be return; but only
the first one here will be built as well, so this is in practice
not a problem.
The formatter uses this helper to get the tree pipeline  via its
name wherever it is needed.
This also adds an `__iter__` method `Manifest` to ease iterating
over just the pipeline values, a la `for pipeline in manifet`.
2021-01-22 15:03:19 +01:00
Christian Kellner
88acd7bb00 pipeline: make them "exportable"
Add a new `export` property to the `Pipeline` object that indicates
whether a the result, i.e. the tree after the pipelines has been
built, should be exported, i.e. copied to the output directory.
In the current format (v1), the main pipeline, gets marked as such
by the corresponding loader.
2021-01-22 15:03:19 +01:00
Christian Kellner
42dd3c1e2d manifest: add and use add_pipeline method
Instead of passing all pre-created pipelines to the Manifest
constructor, add a `add_pipeline` method, analogous to the
existing `Pipeline.add_{stage, assembler}` methods. Convert
the format loading code to use that and remove the constructor
parameter.
2021-01-22 15:03:19 +01:00
Christian Kellner
673ea0dfca formats/v1: properly format failed results
When the build fails, not all pipelines might have been built and
those pipelines will be missing from the results. Currently the
code assumes that all pipelines will have a result and this will
crash when trying to find an id for an pipeline that did not get
built.
2021-01-20 21:27:17 +01:00
Christian Kellner
8ccc73d1c3 pipeline assemblers are stages now
Instead of using the `Assemblers` class to represent assemblers,
use the `Stage` class: The `Pipeline.add_assembler` method will
now instantiate and `Stage` instead of an `Assembler`. The tree
that the pipeline built is converted to an Input (while loading
the manifest description in `format/v1.py`) and all existing
assemblers are converted to use that input as the tree input.

The assembler run test is removed as the Assembler class itself
is not used (i.e. run) anymore.
2021-01-18 17:44:46 +01:00
Christian Kellner
7a6c2df910 stage: add module information about itself
Add a new `info` property that holds the `meta.ModuleInfo` info
for the stage. This gives each instance of a stage access to
meta (or class) information about it, i.e. its schema, docs but,
more importantly, also its name and path to the executable.
Thefore the `name` property is coverted into a transient property
which access the `name` member of `info`.
Change the `formats/v1` load mechanism to carry a new `index`
argument which is used to load the `ModuleInfo` for each stage.
Adapt all tests to load the info as well when creating stages.
2021-01-18 17:44:46 +01:00