Commit graph

384 commits

Author SHA1 Message Date
Tom Gundersen
bbd8dc338d distro: introduce Arch and ImageType interfaces
Objects implementing these interfaces will represent the
architecture support for a given distro and the image type
support for a given architecture distro combination, respectively.

The idea is to always resolve to these objects early, and drop
the equilavent methods from the distro interface. This means that
we convert our input strings to real objects once, and then never
have to verify their correctness again.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-23 15:43:55 +01:00
Tom Gundersen
ff0ec01eb6 distro: drop NewDefaultRegistry()
Require the caller to pass in the required distros explicitly. This
would allow us to easily add distros in osbuild-pipeline and tests
before exposing them in composer itself, for instance.

This means there is no longer a dependency from the distro package
to each of the individual distros, so the distros are now able
to depend on the distro packag for types and interfaces.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-23 15:43:55 +01:00
Tom Gundersen
08ff8ab81b distro: the distro constructors cannot fail
Simplify the code by dropping the potential error return. The
constructor simply instantiates some maps, this cannot fail.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-23 15:43:55 +01:00
Tom Gundersen
1345ca77fd store: drop the distro registry
This was now unused.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-22 22:26:09 +01:00
Tom Gundersen
0656fdcd38 store: don't query the distro for the filename
The LocalTarget contains the filename, so look it up there instead.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-22 22:26:09 +01:00
Tom Gundersen
839b22026e target: pass the image filename in each target
Rather than having to assume that we only ever produce one
artifact, have each upload target contain the filename it expects
to upload from the osbuild output.

An image file is always explicitly named in the manifest, and we
leave it up to each distro to decide how this is done, but the
convention is to use the same image filename as used when
downloading the image through weldr.

Now make this policy explicit, by quering the distro for the image
name and inserting it into each upload target.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-22 22:26:09 +01:00
Tom Gundersen
61836a7079 weldr/upload: no longer reuse the structs from the target package
For serializeation, make our own private structs. The structs
in the target package are not exactly the same as the ones used by
weldr, so in order to avoid too many compromises, let's just do
an explicity translation.

As a general principle, we aim to only use private types for
serialization and rather translate than reuse for different
purposes.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-22 22:26:09 +01:00
Tom Gundersen
440a5acb41 weldr/upload: make translations between upload options explicit
The same types are used in the weldr API as internally. We want
to avoid sharing serialized types like this, as it easily leads
to layering vialotions.

For now just make the translation explicity, in a follow-up
we will introduce types dedicated to serialization in the weldr
API.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-22 22:26:09 +01:00
Lars Karlitski
069ccba894 store: pass repos to PushCompose
Repositories were not passed down into `Distro.Manifest()`. This makes
all builds fail, because these repositories are use to access gpgkeys.
2020-03-21 11:08:16 +01:00
Lars Karlitski
77556973cc distro: don't expose repositories in distro objects
Mixing the way to build a distribution with where to get the source
packages from is wrong: it breaks pre-release repos, local mirrors, and
other use cases. To accommodate those, we introduced
`/etc/osbuild-composer/repositories`.

However, that doesn't work for the RCM API, which receives repository
URLs to use from outside requests. This API has been wrongly using the
`additionalRepos` parameter to inject those repos. That's broken,
because the resulting manifests contained both the installed repos and
the repos from the request.

To fix this, stop exposing repositories from the distros, but require
passing them on every call to `Manifest()`. This makes `additionalRepos`
redundant.

Fixes #341
2020-03-18 20:46:28 +01:00
Lars Karlitski
1b7cb6c11b store/jobqueue: remove distro field from jobs
A job's purpose is to build an osbuild manifest and upload the results
somewhere. It should not know about which distro was used to generate
the pipeline.

Workers depended on the distro package in two ways:

1. To set an osbuild `--build-env`. This is not necessary anymore in new
   versions of osbuild. More importantly, it was wrong: it passed the
   runner from the distro that is being built, instead of one that
   matches the host.

   This patch simply removes that logic.

2. To fetch the output filename with `Distro.FilenameFromType()`. While
   that is useful, I don't think it warrants the dependency.

   This patch uses the fact that all current pipelines output exactly
   one file and uploads that. This should probably be extended in the
   future to upload all output files, or to name them explicitly in the
   upload target.

The worker should now compile to a smaller binary and do less
unnecessary work on startup (like reading repository files).
2020-03-18 12:24:20 +01:00
Lars Karlitski
e70e6a72a0 weldr: remove azure-specific size check
This is already done by the distros.
2020-03-18 08:33:42 +01:00
Lars Karlitski
baa055d6ee rcm: use same function as weldr for pushing composes
Now that `Store.PushCompose()` takes a `Distro` as argument, the rcm API
can use that function as well. This moves them both through the same
code path, reducing duplication.

Remove `PushComposeRequest()` and the corresponding struct. It was
supposed to allow composes with multiple output types and architectures,
but that was not yet implemented. Merging the two now simplifies moving
the compose queue out of the store in a future commit, which will then
tackle multi-image-type composes as well.
2020-03-18 08:33:42 +01:00
Lars Karlitski
0f1a014aca store: don't keep a "default" distro
Only the weldr API has the concept of a default distro. Pass that distro
explicitly to `PushCompose()` and fetch the distro from the compose in
all other functions that accessed Store.Distro.
2020-03-18 08:33:42 +01:00
Lars Karlitski
15033faa81 rcm: pass packages when pushing a compose
In the post-dnf-stage world, `Distro.Manifest` expects the full list of
depsolved packages.  This is similar to what weldr does, but much
simpler, because the rcm API only cares about base packages.
2020-03-18 08:33:42 +01:00
Lars Karlitski
c2c8fae093 store: give ComposeRequest a real distro
`ComposeRequest` included a `common.Distribution`, which had to be
resolved in PushComposeRequest. Use a real `distro.Distro` object here,
and push resolving it to the rcm package.

Change the `Distribution` on the (lower-case) `composeRequest` to a
string. This struct represents the incoming request. Since we're now
resolving the real distro object from the registry in the same function,
it seems redundant to validate the incoming distro twice.
2020-03-18 08:33:42 +01:00
Lars Karlitski
f68679c09f weldr: remove unused argument
819430e removed all `clean` arguments from rpmmd. This was a leftover.
2020-03-18 08:33:42 +01:00
Brian C. Lane
548c58ddda weldrcheck: Convert to go testing framework + testify/require
Convert weldrcheck to use the standard go testing framework along with
the github.com/stretchr/testify/require assert package.

This also removes the cmd/osbuild-weldr-tests and builds the test binary
directly from the weldrcheck package. This makes it easier to organize
the code instead of putting it all into a single main_test.go file.
2020-03-17 21:10:00 +01:00
Ondřej Budai
54e27e607c stage: make the unmarshalling error more verbose
Prior this commit there was no information in the log about the unrecognized
stage. This commit adds the stage name to the unmarshalling error.
2020-03-17 12:21:01 +01:00
Tom Gundersen
7957feff48 distro.Manifest: take Customizations rather than Blueprint as argument
This makes two changes simultaneously, to avoid too much churn:
 - move accessors from being on the blueprint struct to the
   customizations struct, and
 - pass the customizations struct rather than the whole blueprint
   as argumnet to distro.Manifest().

@larskarlitski pointed out in a previous review that it feels
redundant to pass the whole blueprint as well as the list of
packages to the Manifest funciton. Indeed it is, so this
simplifies things a bit.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-15 23:48:42 +01:00
Tom Gundersen
5d179428be rpmmd: drop the Name attribute from RepoConfig
This was never actually used anywhere, as passing it to dnf-json
was a noop.

We may want to reconsider the concept of a source/repo name and
how it differs from an ID, but for now drop the name.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-15 23:48:42 +01:00
Tom Gundersen
7ea74cd131 dnf-json: pass back the repo_id and the relativepath of each package
This will eventually replace the remote_location property. The latter
pins a specific location (a specific mirror), but the two former
can together be used to re-resolve to a more suitable mirror at the
time/place the package will actually be downloaded.

Rather than pinning mirrors in the osbuild manifests, we want to be
able to include the metalink and relative locations so each worker
can use mirrors closer to them.

This would be particularly important when pipelines are rebuilt in
the future, and the best mirrors may have changed.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-15 23:48:42 +01:00
Tom Gundersen
6309611fea distro: avoid nil-pointer dereference on error
When a key is not fonud, there is no `err` variable set, so we should
not attempt to print it.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-15 19:38:59 +01:00
Tom Gundersen
8400b39577 distro.Manifest: drop checksums parameter
This is no longer used to generate pipelines, but has been replaced
by the package specs.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-15 19:38:59 +01:00
Tom Gundersen
819430e659 rpmmd: no longer flush the caches on every call
When we used the dnf-based pipelines, we were relying on the fact
that the metadata was unlikely to have changed between we generated
the pipeline and called osbuild. We achieved this by always updating
to the most recent metadata on every call to rpmmd.Depsolve that
would end up in a pipelin.

Refreshing the metadata is time-consuming, and something we want
to avoid if at all possible. Now that our pipelines no longer
rely on this property, we can drop the flushing.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-15 19:38:59 +01:00
Tom Gundersen
8d3be9e2c0 osbuild/stages: drop the dnf stage
This is no longer used, and will be deprecated in osbuild eventually.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-15 19:38:59 +01:00
Tom Gundersen
4c40faebe6 distro: move from dnf-based to rpm-based pipelines for all distros
Conceptually, we used to insert the high-level packages and package
groups into the pipeline together with the expected repository
metadata checksum.

osbuild, using the dnf stage, would then fetch the metadata, verify
that its checksum is correct, compute the dependencies, and install
the packages.

Among the problems this has is that it made it impossible to cache
and share the resolved metadata as well as the rpms. Moreover,
as the checksum was at the repository-level, rather than at the
package level, it meant that we would refuse to build a pipeline
as soon as there were any changes at all to the repository, as we
could no longer guarantee the installed packages would be the same.

As of this patch, all repository and metadata handling is done by
composer, rather than osbuild. This means that the resolved metadata
can be cached between runs, which and it means that we can now
pin individual packages, rather than the entire repository. Meaning,
that as long as the rpms are still available, we are able to build
a pipeline.

The downloading of rpms is now done by a source helper in osbuild,
which means that they can be cached and shared between runs too.

One consequence of this change is that we resolve the location of
each rpm in composer, and pass that to the worker. As the worker
may not be in the same location, we do not want to use metalinks
in composer for this, as it would pin the repository closest to
composer, rather than the runner. Instead, we now manually select
a baseurl for each repository, which should be generally the
most useful one. Fedora helpfully provides such baseurls, so
this should work ok.

The most important thing to verify when checking this commit, is
that the image info in our test-cases remains unchanged.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-15 19:38:59 +01:00
Tom Gundersen
0f2b8e597e distro/test: use cmp.Diff rather than reflect.DeepEqual
This gives us more readable output. Both because it gives just a
diff, rather than the whole object as a string, but also as it
captures differences between the objects that thir string
representation does not.

In particular, if a field is an interface I, and T implements I,
then an object of type T and a pointer to the same object can both
be assigned to a variable of type I. Either way, the JSON
representation is the same, but the objects (correctly) do not
compare equal.

This is a pain to debug.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-15 19:38:59 +01:00
Lars Karlitski
72f8b07e8b store: move ComposeRequest to the store package
A ComposeRequest is data used to submit a compose to the store, so it
should live in that package.

Remove the json marshalling test, because ComposeRequest is never
marshalled to JSON.

This will allow to use types from `distro` in the ComposeRequest struct.
2020-03-12 20:01:24 +01:00
Brian C. Lane
e3d1a34ab6 weldr: Fix blueprints/depsolve response
The response always returns a 200 with a JSON response. Any errors will
be in the errors list.
2020-03-12 01:55:45 +01:00
Brian C. Lane
e13ebd46ee weldr: Fix blueprints/info response for unknown blueprints
The response is different for JSON and TOML requests. If it is JSON it
will always return a 200, but any blueprints with errors will be in the
errors list.

If TOML has an error it will return an error 400 with the error in a
standard API error response with status set to false.
2020-03-12 01:55:45 +01:00
Brian C. Lane
7bd020ca11 weldr: Return an error when an empty blueprint is received
The JSON and TOML parsers differ in how they handle an empty body so
check for a ContentLength of zero first and return a "Missing
blueprint" error to the client.

Includes updated tests for the JSON path, and new tests for empty TOML
blueprints.
2020-03-12 01:55:45 +01:00
Brian C. Lane
77fd2a0d8b store: Return an error from GetBlueprintChange
If the blueprint doesn't exist, or the commit for the selected blueprint
doesn't exist it will return an error.

This also fixes the blueprints/undo/ route to return the correct error
to the caller.
2020-03-12 01:55:45 +01:00
Brian C. Lane
b4710b52f1 store: Return an error from DeleteBlueprint and DeleteBlueprintFromWorkspace
If an unknown blueprint or workspace is deleted it will now return an
error.

Also fixes the blueprints DELETE handlers to return the correct error to
the client. Includes a new test.
2020-03-12 01:55:45 +01:00
Brian C. Lane
2675eff4eb weldr: Add tests for empty and invalid blueprints 2020-03-12 01:55:45 +01:00
Brian C. Lane
36c19d756a weldrcheck: Add tests for blueprint errors
Add tests for things like posting invalid or empty blueprints,
non-existent blueprints, and commits.
2020-03-12 01:55:45 +01:00
Brian C. Lane
aed28ccf72 store: Add blueprint change order tracking
Previously the order that changes were made to blueprints was not being
saved. I worked around this by sorting by timestamp, but it only has 1s
resolution so it is very likely to end up with changes having the same
timestamp, especially when running tests.

This adds a new variable to the Store, it is a list of the commit hashes
for each blueprint, in the order they were made.

Since this is a change to the Store schema the first time the new code
is run with the old store state it needs to populate the commit list, as
best it can, with the existing data. To do that it sorts the changes for
each blueprint by timestamp and version and saves this ordering into the
new BlueprintsCommits list.
2020-03-10 12:41:19 +01:00
Brian C. Lane
eeef1e289c weldr: Add support for /blueprints/tag route
A POST to this route will tag the latest commit of a blueprint as a new
revision. The revision numbers start at 1 and increment on each call.
If the latest commit has already been tagged it ignores the request.
2020-03-10 12:41:19 +01:00
Brian C. Lane
cc7bab14af store: Add TagBlueprint function
This function will find the latest commit to a blueprint and increment
the revision, or set it to 1 if this is the first tag for the blueprint.
2020-03-10 12:41:19 +01:00
Brian C. Lane
46c3bed153 client: Use http.Client instead of a string for the socket
This converts the client and weldrcheck functions to use http.Client for
connections instead of passing around the socket path and opening it for
each test.
2020-03-09 18:02:54 +01:00
Tom Gundersen
16e01f01d6 distro: drop Pipeline and Sources from interface
These are no longer used directly, but superseeded by Manifest().

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-08 21:05:01 +01:00
Tom Gundersen
fc47ae8c39 test/cases: test manifests rather than pipelines
A manifest is struct made up of a pipeline and a sources object. So
far all our sources objects are empty, but we have moved from
using pipelines to manifests everywhere, in preparation for
generating pipelines that require sources.

Make the same change in the test cases.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-08 21:05:01 +01:00
Tom Gundersen
2facde159b distro/test: fix typos in log messages
Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-08 21:05:01 +01:00
Tom Gundersen
caca553a8f test/cases: rename compose -> compose-request
This is to avoid any confusion with the Compose struct in the store,
which contains the pinned rpmmd data and the pipeline, among other
things.

The struct in the test cases represent the user input to the compose
route, so rename it 'compose-request', to make that clearer.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-08 21:05:01 +01:00
Tom Gundersen
d7297e569d test/cases: support package specs in the rpmmd struct
This is unused for now, but we support passing the actual package specs
return from rpmmd.Depsolve() to distro.Pipeline(), so we should support
doing that also in the tests.

So far all our distros ignore the passed in packages, so no test-cases
make use of this yet.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-08 21:05:01 +01:00
Tom Gundersen
fbf137a1b7 test/cases: move checksum out of the compose struct
The intention is that the compose struct fully specifies the test
case, and pipeline and image-info specifies the expected outputs.
Lastly, the boot struct specifies how to boot-test the image.

The checksum does not fit into this scheme, as it is computed from
the compose by querying rpmmd, and it is then passed as an input to
distro.Pipeline in order to compute the pipeline.

Introduce a new struct, rpmmd, which will eventually contain all
the data returned from rpmmd.Depsolve and later passed to
distro.Pipeline. For now it only contains the checksum.

This is not a functional change.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-08 21:05:01 +01:00
Jacob Kozol
4690320503 blueprint: add default version
If the user creates a new blueprint with no version specified, the
blueprint struct uses "0.0.0" as the default version. Blueprint tests
for a blueprint with an empty version now expect no error.
2020-03-04 19:20:58 +01:00
Tom Gundersen
571932db37 job: pass manifest instead of pipeline to osbuild
This is not a behavioral change, as all distros currently use
empty source objects. But when we move over to rpm-based pipelines,
this will change.

Make the same change to osbuild-pipeline, so these stay in sync.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-03 22:25:49 +01:00
Tom Gundersen
919c484c79 distro: add Manifest method to interface
For now, this simply wraps Pipeline and Sources, and retruns the
resulting manifest object. In the future, Pipeline and Sources
may be dropped from the interface.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-03 22:25:49 +01:00
Tom Gundersen
4da1ab03b3 osbuild: introduce manifest concept
A manifest is simply a struct containing a sources and a pipeline
object. We want to store and transfer pielines always with their
sources, and will use the manifest for this.

When serialized, a manifest can be the input to `osbuild`, just
like a bare pipeline can be. This means there will be no need
to pass in sources separately on the commandline.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-03-03 22:25:49 +01:00