Commit graph

64 commits

Author SHA1 Message Date
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
Christian Kellner
698635171c pipeline: refactor args for add_stage
All tests and invocations of `add_stage` actually pass a valid
options dictionary. Thefore move the `options` args before
the `sources` arg and remove the default value (`None`).
2021-01-18 17:44:46 +01:00
Christian Kellner
262877091f osbuild: flatten the pipeline
Instead of having build pipelines nested within the pipeline it is
the build pipeline for, the nested structure is transferred into a
flat list of pipelines. As a result the recursion is gone and all
the pipelines and trees are build one after the other. This is now
possible since floating objects are kept alive by the store itself
and all trees that are being built are transparently via them.
The immediate result dictionary changed accordingly. To keep the
JSON output of osbuild the same, the result is now routed through
a format specific converter.
Additionally, the v1 format module gained a function to retrieve
the global tree_id and output_id. With the new models those global
ids will go away eventually and thus need to go through the format
specific code.
2021-01-15 13:20:31 +01:00
Christian Kellner
f38c48086e pipeline: run method takes store object not dir
Instead of passing the store directory to Pipeline.run, pass an
already initialized ObjectStore object. This binds the lifetime
of the store and its (temporary) objects to the run of osbuild
not the run of the pipeline.
This prepares re-using the stores with multiple (non-nested)
pipelines.
2021-01-15 13:20:31 +01:00
Christian Kellner
d25936a028 formats: describe now takes a manifest
Instead of a pipeline, describe now takes a Manifest instance.
The reason is that a manifest fully describes the build, which
includes the sources. Now that the describe function takes the
manifest, the sources can be included as well.
Adapt the tests to refelect that change.
2021-01-09 18:09:47 +01:00
Christian Kellner
945914b195 osbuild: introduce Manifest class
The 'Manifest' class represents what to build and the necessary
sources to do so. For now thus it is just a combination of the
pipeline the source options.
2021-01-09 18:09:47 +01:00
Christian Kellner
4ab52c3764 formats: move pipeline description here
The description of a pipeline is format dependent and thus needs
to be located at the specific format module.
Temporarily remove two tests; they should be added back to a format
specific test suit.
2021-01-09 18:09:47 +01:00
Christian Kellner
a13783f67b formats: load function takes combined manifest
Instead of having the pipeline and the source option as separate
arguments, the load function now takes the full manifest, which
has those two items combined.
2021-01-09 18:09:47 +01:00
Christian Kellner
0b6f36158d osbuild: use load function via the format module
Instead of importing the load, load_build functions into the osbuild
namespace and using it via that, use the load function via the module
that provides them, i.e. the formats.v1 module.
2021-01-09 18:09:47 +01:00
Christian Kellner
b65211a94d formats/v1: move validation logic here
The validation of the manifest descritpion is eo ipso format
specific and thus belongs into the format specific module.
Adapt all usages throughout the codebase to directly use the
version 1 specific function.
2021-01-09 18:09:47 +01:00
Christian Kellner
d7d84a8eb1 test/mod: use proper host runner
Instead of hard-coding the use of the "org.osbuild.linux" runner,
use the new `osbuild.pipeline.detect_host_runner` function to
dynamically detect the runner for the host system. That should fix
the tests on RHEL systems, where python3 is by default not present
and even if it is manually installed, is an indirection via
alternatives (i.e. a link to /etc/alternatives), which must be
explicitly configured in the build root container for the host.
2020-10-21 11:13:28 +02:00
Christian Kellner
25662fbfbc test/buildroot: more lenient output test checking
In `test_output`, require that the test string is found in the
output, not equal to the output. Other warnings or log messages
might be printed by the runner.
2020-10-21 11:13:28 +02:00
Christian Kellner
9ef642228f test: adapt 'libdir' argument for BuildRoot's ctor
As of commit 1e3c0ae "unified libdir handling", the libdir argument
for the BuildRoot constructor is not a keyword argument anymore.
Adapt the argument accordingly.
2020-10-21 11:13:28 +02:00
Christian Kellner
71f7bf8930 test/api: assert return code for api.exception
Check that the exit code for `api.exception`, called via the
`api.exception_handler` helper, is the correct one.
2020-10-09 10:47:44 +02:00
Christian Kellner
aaa51e22a6 api: properly serialize the exception's traceback
Use `traceback.print_tb()` to serialize the exceptions' backtrace.
The previously used expression `str(e.__traceback__)` will just
give `<traceback object at 0x…>`, which is not very helpful.
Add a test to check that the method name that raises the exception,
also called `exception`, is in the traceback.
2020-10-09 10:47:44 +02:00
Christian Kellner
7a112c27cb test/api: fix white-space error
No double space between class methods, so say the scriptures.
2020-10-09 10:47:44 +02:00
Christian Kellner
f8de164413 api: properly encode exception type
When using `str(type(exception))` this ends up to be something like
`<class 'ValueError'>` for a `ValueError` exception. Get the vanilla
name of the exception type via `type(exception).__name__`.
Add a test to ensure that we encode this properly.
2020-10-09 10:47:44 +02:00
Christian Kellner
f5d00dd043 api: use more generic error member for exceptions
Rename the `API.exception` member to `API.error`, to make it more
generic, so it can also be used for other sort of errors in the
future. Also add a layer of additional structure with `type` and
`data` members so different types of errors apart. Currently only
`exception` is used.
Adapt the tests in test/mod/test_api.py to check for the new
structure and its content.
2020-10-09 10:47:44 +02:00
Christian Kellner
17fbe41b03 test/api: check api.exception exits the process
The `api.exception` method, which is internally also used by
`api.exception_handler` helper, calls `sys.exit` and this no
statement after a call to either method should be reached.
Add an assertion to make sure of that.
2020-10-09 10:47:44 +02:00
Chloe Kaubisch
5dc5ddcf29 api: add exception endpoint
Create a new api endpoint called exception, that communicates
exception backtraces separately back to osbuild, as opposed to
dumping them into the normal log. Additionally, add a corresponding
test to check that a call to api.exception correctly sets
API.exception.
2020-10-02 17:49:45 +02:00
chloenayon
01aae91949 api: remove setup_stdio
API.setup_stdio was replaced in PRs 506 and 507,
remove setup_stdio functions and call sites.
2020-09-09 12:52:50 +02:00
Christian Kellner
fc0c75f40e test/api: race-free api.metadata access
Access metadata.api only after `api` has exited the context and
thus the event loop has stopped and all incoming messages, like
the one setting the metadata, have been processed.
See commit 803433fb62 for a lecture
about the internals and all the details involved.
2020-08-31 15:06:36 +02:00
Christian Kellner
a3934ab947 test/buildroot: check BuildRoot.output
Now that the `org.osbuild.linux` runner does not use `api.setup_stdio`
anymore, the output of the binary run from the BuildRoot must end up
in `BuildRoot.output`. Check for that.
2020-08-31 15:06:36 +02:00
Christian Kellner
10579ee6f5 buildroot: return a new CompletedBuild with output
Create a new CompletedBuild object that wraps and is very similar
to the subprocess.CompletedProcess, i.e. it has a process member
but also has shortcuts for returncode. Additionally, the output
of the process is not only forwarded to the monitor, but also
captured and then handed to CompletedBuild, so its output member
will actually contain the full build output. To be compatible
with the previously returned CompletedProcess, `stderr`, `stdout`
members exist on CompletedBuild that also return `output`.
2020-08-31 15:06:36 +02:00
Christian Kellner
ba94409d23 test/buildroot: check we log bwrap's error output
Check that any errors that bubblewrap spits out on stderr make it
to the log. A common case of bubblewrap failing is a runner failing
to execute.
2020-08-27 08:07:14 +02:00
Christian Kellner
96a5499ed9 buildroot: log bubblewrap's output
In case that bubblewrap fails to, e.g. because it fails to execute
the runner, it will print an error message to stderr. Currently,
this output is not capture and thus not logged. To fix that, the
`BuildRoot.run` method now takes a monitor object and will stream
stdout/stderr to the log via the monitor.
2020-08-27 08:07:14 +02:00
Christian Kellner
fc5e0070c5 test/api: check for 'get-arguments'/api.arguments
Simple check for the new server side method, `get-arguments`, and
client side counterpart, `api.arguments`, that compares that using
the later we get the supplied input (arguments) to API.
2020-08-25 18:51:55 +02:00
David Rheinsberg
803433fb62 api: prevent early output retrieval
Change the API endpoint to prevent retrieving monitor-output from a
running instance. Instead, we require the caller to exit the API context
before querying the monitor-output. This guarantees that the api-thread
was synchronously taken down and scheduled any outstanding events.

This fixes an issue where a side-channel notifies us of a buildroot
exit, but the api-thread has not yet returned from epoll, and thus might
not have dispatched pending I/O events, yet. If we instead wait for the
thread to exit, we have a synchronous shutdown and know that all
*ordered* kernel events must have been handled.

In particular, imagine a build-root program running (like `echo` in the
test_monitor unittest) which writes data to the stdout-pipe and then
immediately exits. The syscall-order guarantees that the data is written
to the pipe before the SIGCHLD is sent (or wait(2) returns). However, we
retrieve the SIGCHLD from our main-thread usually (p.join() in our test,
and BuildRoot() in our main code), while the pipe-reading is done from
an API thread. Therefore, we might end up handling the SIGCHLD first
(just imagine a single-threaded CPU that schedules the main task before
the thread). To avoid this race, we can simply synchronize with the
api-thread. Since we already have this synchronization as part of the
api-thread takedown, it is as simple as stopping the api-thread before
continuing with operations.

Lastly, if a write operation to a pipe was issued, we are guaranteed
that a SIGCHLD synchronization across processes is ordered correctly.
Furthermore, the python event-loop also guarantees that stopping an
event-loop will necessarily dispatch all outstanding events. A read is
guaranteed to be outstanding in our race-scenario, so the read will be
dispatched. The only possible problem is `_output_ready()` only
dispatching a maximum of 4096 bytes. This might need to be fixed
separately. A comment is left in place.
2020-08-13 14:02:27 +02:00
Christian Kellner
30ad32b174 test/api: checks for metadata passing
Add a simple check to make sure that metadata passing via the api
client and api endpoint is working.
2020-08-13 10:50:34 +02:00
Christian Kellner
e0b7361b26 test/buildroot: check selinuxfs is read-only
This is a crucial pre-condition for the org.osbuild.selinux stage
to work properly, especially that it can set labels that are not
present in the policy on the host. If /sys/fs/selinux is writable,
setfiles will try to verify the labels via /sys/fs/selinux/context
and fail for unknown labels.
2020-08-12 16:52:27 +02:00
Christian Kellner
e2231a8bd2 test/buildroot: simple check for bind mounts
Check that bind-mounting works and read only bind mounts are indeed
read-only and "normal" bind mounts are read-write.
2020-08-12 16:52:27 +02:00
Christian Kellner
28cea491bd test: move api buildroot test to test_buildroot.py
Create a new test suite for BuildRoot related test and move the
the combined api and buildroot check there.
2020-08-12 16:52:27 +02:00
chloenayon
1e3c0aea1b osbuild: unified libdir handling
Change the default of libdir to /usr/lib/osbuild and
remove redundant logic. Additionally, change how the
python package is detected.

Instead of checking if libdir is None, check if
/usr/lib/osbuild is empty - i.e. if the user has specified
a different directory than the default.
2020-08-04 09:02:22 +02:00
Christian Kellner
785f843901 jsoncomm: remove destination from send
Now that jsoncomm.Socket is using a connection-oriented socket,
the destination in `socket.sendmsg` is ignored and thus can and
should be dropped from the `jsoncomm.Socket.send` method.
Adjust the tests accordingly.
2020-07-29 02:16:20 +01:00
Christian Kellner
43db8082bd test/jsoncomm: check accept with no clients
Ensure that if `accept` is called on a normal listener socket, i.e.
the socket is in non-blocking mode, `None` is returned.
2020-07-29 02:16:20 +01:00
Christian Kellner
8388a64ffa api: remove 'addr' param from message dispatcher
Now that jsoncomm is using a connection oriented protocol, the
`addr` parameter is not needed[*] and can thus be removed from
the `BaseAPI._message` message dispatcher. Adapt all usages
of it, including the tests.

[*] sendmsg ignores the destination parameter for connection
oriented sockets.
2020-07-29 02:16:20 +01:00
Christian Kellner
abbdf06ba5 jsoncomm: switch to use sequenced-packet sockets
Switch to use a connection oriented datagram based protocol, i.e.
`SOCK_SEQPACKET`, instead of `SOCK_DGRAM`. It sill preserves
message boundaries, but since it is connection oriented the client
nor the server do not need to specify the destination addresses
of the peer in sendmsg/recvmesg. Moreover, the host will be able
to send messages to the client, even if the latter is sandboxed
with a separate network namespace. In the `SOCK_DRAM` case the
auto-bound address of the client would not be visible to the host
and thus sending messages would to it would fail.

Adapt the jsoncomm tests as well as `BaseAPI`.
2020-07-29 02:16:20 +01:00
Christian Kellner
6f8b850ef2 test/api: add build root integration check
Add a new test that checks the integration of API end points with
the `BuildRoot`.
2020-07-27 12:50:38 +01:00
Christian Kellner
c236039e0d test/api: use high level message dispatcher
Use the new `BaseAPI._message` high level message dispatcher that
is more convenient to use.
2020-07-27 12:50:38 +01:00
Christian Kellner
0c7284572e osbuild: auto-generate socket addresses for APIs
Rely on the ability of `BaseAPI` to auto-generate socket addresses
when no one was provided. The `BuildRoot` does not rely on the
sockets being created in the `BuildRoot.api` directory anymore and
will instead bind-mount each individual socket address to the well
known location via the `BaseAPI.endpoint` identifier.
Convert all API providers to take the `socket_address` as an
optional keyword argument.
2020-07-27 12:50:38 +01:00
Christian Kellner
28947f3bae util/jsoncomm: support PathLike
Add support for `util.types.PathLike` paths for socket addresses,
instead of just plain strings. Test it by using pathlib.Path to
create the address in the corresponding test.
2020-07-27 12:50:38 +01:00
Christian Kellner
bc81e68727 api: each API defines its 'endpoint' name
Add a new abstract class property to `BaseAPI` called `endpoint`,
meant to be implemented by deriving classes in order to identify
the end point name for the API provider.
Implement the new property in all existing API providers.
2020-07-27 12:50:38 +01:00
Christian Kellner
38e714f229 test/monitor: use osbuild.api.setup_stdio
Use the new `api.setup_stdio` instead of providing an exact copy
of that in the test code.
2020-07-27 12:50:38 +01:00
Christian Kellner
b86b6a4bf8 test/api: add checks for the api infrastructure
Add a check for `api.BaseAPI` by implementing a test API and test
that receiving messages and dispatching them works as planned.
2020-07-27 12:50:38 +01:00
Christian Kellner
1ce517e595 api: extract base class
Split out the part of `api.API` that is responsible for providing
the server infrastructure for the API; i.e. setting up the server
and the corresponding context manager and asynchronous event
handling. This leaves `API` itself which just the implementation
of the high level protocol and makes the API-server part re-usable.

NB: pylint, for some reason, confuses `API` and `BaseAPI`, like in
`test_monitor`. Annotate that accordingly.
2020-07-27 12:50:38 +01:00
Christian Kellner
5142046396 test/osbuild: add run tests for stages, assembler
Create small test cases that check the execution of Stages and
Assembler. This ensure that path handling, the sandbox, as well
as basic result reporting works as expected.
2020-07-22 09:37:30 +01:00
Christian Kellner
ec531ee9ed test/osbuild: fix whitespace
Fix indent of pipeline definition.
2020-07-22 09:37:30 +01:00
Christian Kellner
80e96c8494 test/objectstore: proper path concatenation
Instead of using string interpolation and concatenation to build
file system paths, use `os.path.join` or directly the constructor
for `pathlib.Path`, which can take path segments.
2020-07-22 09:37:30 +01:00
Christian Kellner
d3a97a90a5 test/monitor: check monitor functions are invoked
Create a new monitor that records all the invocations of the
monitoring (virtual) functions and use that to check that when
running (i.e. building) a pipeline all of them are executed
the excepted number of times (and with the correct arguments).
2020-07-21 13:25:04 +02:00
Christian Kellner
5d226b2e15 test: add basic checks for monitoring and API
Add a basic test that will set up an 'API' endpoint, then spawn a
child process that uses that 'API' endpoint to setup its stdio in
very much the same way as runners do. This is used to verify that
the API itself works properly as well as the new LogMonitor class
by comparing the inputs and outputs.
2020-07-21 13:25:04 +02:00