Commit graph

43 commits

Author SHA1 Message Date
sanne
0ea31c39d5 worker: Add identity filter and client oauth support 2021-06-17 10:08:35 +02:00
Achilleas Koutsou
668fb003ef jobqueue: Replace JobArgs() with Job()
JobArgs() function replaced with more general Job() function that
returns all the parameters used to originally define a job during
Enqueue(). This new function enables access to the type of a job in the
queue, which wasn't available until now (except when Dequeueing).
2021-01-19 10:37:51 +01:00
Achilleas Koutsou
1c5f6810be worker: Add JobArgs() method
Wraps jobqueue.JobArgs() method and unmarshals data into the provided
concrete struct value. The struct should match the requested job type of
the given ID.
2021-01-16 13:39:30 +01:00
Ondřej Budai
e10a7f1ccc {koji,worker}/server: log errors returned from handlers
Previously, we had no clue what errors were catched by the default echo's
error handler. Thus, in the case of an error, we were basically blind. Let's
log all errors so we can investigate them later.

Signed-off-by: Ondřej Budai <ondrej@budai.cz>
2020-12-02 08:52:27 +01:00
Ondřej Budai
978e309153 worker/server: move it to the style of koji server
The previous code was smelling a bit (e.g. Server.server field) so I decided
to rewrite it in the style of the much nicer koji server.

Not a functional change.

Signed-off-by: Ondřej Budai <ondrej@budai.cz>
2020-11-19 17:39:24 +00:00
Tom Gundersen
c777a18df0 jobqueue: expose dependencies when querying status
The status of a job may depend on the status of its dependenices,
as we do not repeat for instance the failed state in each dependent
job.

Return also the list of dependencies so these can be queried too.
2020-11-11 18:16:42 +01:00
Tom Gundersen
98fd290a08 worker: make Enqueue() specific for each job type
Most of the worker API is now untyped, but keep Enqueu() typed to
ensure the job objects match the names in the queue. This means we
must add a version of Enqueue() for each job type we support.
2020-11-11 18:16:42 +01:00
Tom Gundersen
79f87ea347 worker/RequestJob: treat 'osbuild-koji' jobs like 'osbuild' ones
We must special-case the treatment of architecture, to select the
correct remote worker for any job that requires a specific
architecture. For now this means any jobs that run osbuild.
2020-11-11 18:16:42 +01:00
Tom Gundersen
a2895376ae worker: introduce dynamicArgs
In addition to the arguments passed when scheduling a job, a job now
also takes the results of its dependencies as additional arguments. We
call these dynamic arguments for the lack of a better term.

The immediate use-case for this is to allow koji jobs to be split up
as follows:
 - koji-init: Creates a koji build, and returns us a token.
 - osbuild-koji: one job per architecture, depending on koji-init
   having succeeded. Builds the image, and uploads it to koji,
   returning metadata about the image produced.
 - koji-finalize: uses the token from koji-init and the metadata
   from osbuild-koji to import the build into koji if it succeeded
   or mark it as failed if it failed.
2020-11-11 18:16:42 +01:00
Tom Gundersen
11d0da0b5c jobqueue/JobStatus: return result as json.RawMessage
Similarly to the recent changes to Dequeue(), let the caller unmarshal the
return JSON. This allows us to pass the result on without being able
to unmarshal it.

In follow-up patches, we will pass results of jobs to dependent jobs,
but the worker API does not know about the different job types, nor how
to unmarshal them.
2020-11-11 18:16:42 +01:00
Tom Gundersen
e277501ca3 jobqueue: return dependencies on dequeue
Once a job has been enqueued, there is no way to query its dependencies.

This makes dequeue more symmetric to enqueue by returning the
dependencies that were passed to enqueue, allowing the caller to
query the dependencies and their results.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-11-11 18:16:42 +01:00
Lars Karlitski
59e73a686a worker: generalize job types in the server
The worker server was heavily tied to OSBuildJob(Result). Untie it so
that it can deal with different job types in the future.

This necessitates a change in the jobqueue: Dequeue() now returns the
job type, as well as job arguments as json.RawMessage. This is so that
the server can wait on multiple job types with different argument
types.

The weldr, composer, and koji APIs continue to use only "osbuild" jobs.
2020-11-09 14:17:19 +01:00
Lars Karlitski
299a5e52ab worker: use OSBuildJobResult consistently
Workers reported status via an `osbuild.Result`, which only includes
osbuild output. Make it report OSBuildJobResult instead, which was meant
to be used for this purpose and is already used as the result type in
the jobqueue.

While at it, add any errors produced by targets into this struct, as
well as an overall success flag.

Note that this breaks older workers returning the result of an osbuild
job to a new composer. I think this is fine in this case, for two
reasons:

1. We don't support running different versions of the worker and
composer in the weldr API, and remote workers aren't widely used yet.

2. Both osbuild.Result and worker.OSBuildJobResult have a top-level
`Success` boolean. Thus, logs are lost in such cases, but the overall
status of the compose is not.
2020-11-09 14:17:19 +01:00
Lars Karlitski
0cd7174598 worker: deprecate the local target
Add "image_name" and "stream_optimized" fields to the osbuild job as
replacement for the local target options. The former signifies the name
of the uploaded artifact and whether an artifact should be uploaded at
all (only weldr API). The latter will be deprecated at some point, when
osbuild itself can make streamoptimized vmdk images.

This change separates what have always been two distinct concepts:
artifacts that are reported back to the composer node (in practice
always running on the same machine), and upload targets to clouds and
such. Separating them makes it easier to add job types that only allow
one upload target while keeping artifacts.

Keep the local target around, so that jobs that are scheduled can still
be run after an upgrade.
2020-11-09 14:17:19 +01:00
Lars Karlitski
d1f322ec6f worker: always send status "FINISHED"
The server hasn't used common.ImageBuildState to mark a job as
successful or failed for a long time. Instead, it's using the job's
return argument for that. (Jobs don't have a high-level concept of
failing).

Drop the check in the server, and always send "FINISHED" from the client
for backwards compatibility.
2020-11-09 14:17:19 +01:00
Lars Karlitski
5d2f2402cf worker: drop unused variable 2020-11-09 14:17:19 +01:00
Lars Karlitski
669b612d96 worker: remove State from JobStatus
This state is specific to weldr. Previous commits removed it from the
other APIs, because they use different values.

Move the conversion into the weldr API.
2020-11-09 14:17:19 +01:00
Lars Karlitski
a8ba969f6e worker: prefix all routes with /api/worker/v1
Mention this in the `servers` section of the openapi.yml (relative URLs
are allowed) too, even though our generator does not consider it.
2020-09-24 21:08:56 +01:00
Lars Karlitski
9008a1defc worker: require workers to pass their architecture
Jobs are scheduled with type "osbuild:{arch}", to ensure that workers
only get jobs with the right architecture assigned.
2020-09-23 14:28:52 +01:00
Lars Karlitski
44c2144994 worker: Server.RequestJob → RequestOSBuildJob
This clarifies what it does, at least until its use is expanded to other
job types.
2020-09-23 14:28:52 +01:00
Lars Karlitski
ba6a480e32 worker: require workers to declare job types they accept
For now, workers must send `[ "osbuild" ]`.
2020-09-23 14:28:52 +01:00
Lars Karlitski
d3c99b8e93 worker: allow passing different jobs to workers
Until now, all jobs were put as "osbuild" jobs into the job queue and
the worker API hard-coded sending an osbuild manifest and upload
targets.

Change the API to take a "type" and "args" keys, which are equivalent to
the job-queue's type and args. Workers continue to support only osbuild
jobs, but this makes other jobs possible in the future.
2020-09-23 14:28:52 +01:00
Ondřej Budai
03768e5f18 api/worker, koji: fix race condition when using multiple listeners
When remote worker socket was enabled, this was happening:

e := echo.New()

go func() {
    e.Listener = listener1
    e.Start("")
}()

e.Listener = listener2
e.Start("")

Yeah, this is a race condition. None of the echo's Start methods cannot safely
handle multiple listeners.

This commit fixes this issue by using Echo only as a router for standard
http.Server which handles multiple listeners in a non-racy way.
2020-09-23 09:38:29 +02:00
Lars Karlitski
85423d403c worker: clarify 404 error message
When a token doesn't exist, the URL is invalid. Nothing to do with a
job.
2020-09-11 14:23:24 +01:00
Lars Karlitski
3bedd25087 worker/api: send job id to worker after all
Full circle. After switching the worker to not operate on jobs directly,
send the id anyway, so that workers can print it in their logs.
2020-09-11 14:23:24 +01:00
Lars Karlitski
b03e1254e9 worker/api: remove token in favor of callback URLs
Instead of sending a `token` to workers, send back to URLs:

 1. "location": URL at which the job can be inspected (GET) and updated
    (PATCH).
 2. "artifact_location": URL at which artifacts should be uploaded to.

The actual URLs remain the same, but a client does not need to stitch
them together manually (except appending the artifact's name).

Unfortunately, the client code generated by `deepmap` does not lend
itself to this style of APIs. Use standard http.Client again, which is a
partial revert of 0962fbd30.
2020-09-11 14:23:24 +01:00
Lars Karlitski
ccebfb014c worker: echo.NewHTTPError() does not take format string
Use a plain string where possible and `fmt.Errorf` for internal server
errors (echo converts all non-HTTPError errors to 500s)
2020-09-11 14:23:24 +01:00
Lars Karlitski
26b36ba704 worker/api: introduce job tokens
Don't give out job ids to workers, but `tokens`, which serve as an
indirection. This way, restarting composer won't confuse it when a stray
worker returns a result for a job that was still running. Also,
artifacts are only moved to the final location once a job finishes.

This change breaks backwards compatibility, but we're not yet promising
a stable worker API to anyone.

This drops the transition tests in server_test.go. These don't make much
sense anymore, because there's only one allowed transition, from running
to finished. They heavily relied on job slot ids, which are not easily
accessible with the `TestRoute` API. Overall, adjusting this seemed like
too much work for their benefit.
2020-09-11 14:23:24 +01:00
Lars Karlitski
783a88d8cc worker/api: give operations simpler names
The code generator uses the `operationID` field to generate server
handlers, client functions, and types. Use simpler names to make the
generated code easier to read.
2020-09-11 14:23:24 +01:00
Lars Karlitski
ad11ceecf4 worker: use openapi spec and generated code
Write an openapi spec for the worker API and use `deepmap/oapi-codegen`
to generate scaffolding for the server-side using the `labstack/echo`
server.

Incidentally, echo by default returns the errors in the same format that
worker API always has:

    { "message": "..." }

The API itself is unchanged to make this change easier to understand. It
will be changed to better suit our needs in future commits.
2020-09-06 18:42:23 +01:00
Brian C. Lane
4f3f09fec5 worker: Check OSBuildOutput for nil before using it
It is possible for it to end up as nil so it needs to be checked
everywhere it is used.
2020-06-12 12:45:46 +02:00
Lars Karlitski
27acd03b68 worker: add API support for canceling jobs 2020-06-12 10:00:50 +02:00
Tom Gundersen
0417c6d8bb distro: make the osbuild package internal to the distros
Rather than Manifest() returning an osbuild.Manifest object, introduce a
new distro.Manifest object which represents it as an opaque, JSON
serializable object. This new type has the following properties:

1) its serialization is compatible with the input to osbuild,
2) any valid osbuild input can be deserialized into it, and
3) marshalling and unmarshaling to and from JSON is lossless.

This means that even as we change the subset of valid osbulid manifests
that we support, we can still load any previous state from disk, and it
will continue to work just as before, even though we can no longer
deserialize it into our internal notion of osbuild.Manifest.

This fixes the underlying problem of which #685 was a symptom.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-06-03 00:30:01 +02:00
Lars Karlitski
e06076ed8c worker: add JobArtifact() and DeleteJobArtifacts()
This allows removing the `artifactsDir` from `weldr.API`. It makes more
sense to deal with that directory in one place only.
2020-05-27 16:16:05 +02:00
Major Hayden
0921643fa3 Add health check at /status
There are times where it would be good to monitor that osbuild-composer
is up and running. Add a very simple status check that always returns
200/OK. This can be expanded later to verify that other parts of
osbuild-composer are working properly.

Signed-off-by: Major Hayden <major@redhat.com>
2020-05-26 15:34:16 -05:00
Lars Karlitski
a1cf3984dc worker: introduce job artifact directory
The `jobs/:job_id/builds/:build_id/image` route was awkward: the
`:jobid` was actually weldr's compose id and `:build_id` was always `0`.

Change it to `jobs/:job_id/artifacts/:name`, where `:job_id` is now a
job id, and `:name` is the name of the artifact to upload. In the
future, it could support uploading more than one artifact.

This allows removing outputs from `store`, which is now back to being a
pure JSON-store. Take care that `weldr` returns (and deletes) images
from the new (or for backwards compatibility, the old) location.

The `org.osbuild.local` target continues to exist as a marker for the
worker to know whether it should upload artifacts.
2020-05-26 10:42:20 +02:00
Ondřej Budai
e4d32f9e2f worker/server: drop the JobResult method
Let's speak why I merged JobResult and JobStatus together:

Both methods actually called jobqueue.JobStatus(), so performance-wise
there's no real difference and it feels to me that it makes the code simpler:
You don't have to decide which method to call, you just get all the data
about a job in one call. We could split those again when we see some perf
issues with retrieving logs on each status check but I don't think we should
optimize prematurely. Let's leave some work for the future us.
2020-05-19 22:20:20 +02:00
Ondřej Budai
78d5109c81 worker/server: add Result to ComposeStatus
Return also the OsbuildJobResult in ComposeStatus struct. This change will
allow us to remove the JobResult function, see the following commits.
2020-05-19 22:20:20 +02:00
Ondřej Budai
fa5b775718 worker/server: make JobStatus() return JobStatus struct
Personally, I don't like methods returning too much values. I think it's
easy to assign the values in an incorrect order and thus interpreting them
in a wrong way. Also, the following commits will make JobStatus() return
also the JobResult, which would make the number of returned values even
higher.

Not a functional change.
2020-05-19 22:20:20 +02:00
Lars Karlitski
27e8e4b5d5 jobqueue: allow canceling jobs
This is not exposed to a worker yet. It will continue the job and get an
error when it tries to update the job's status to finished.
2020-05-13 16:45:09 +02:00
Lars Karlitski
6773c01722 jobqueue: drop JobStatus type
The enum is redundant information that can be deduced from the job's
times: queuedAt, startedAt, and finishedAt. Not having it reduces the
potential for inconsistent state.
2020-05-13 16:45:09 +02:00
Lars Karlitski
b5769add2c store: move queue out of the store
The store is responsible for two things: user state and the compose queue. This
is problematic, because the rcm API has slightly different semantics from weldr
and only used the queue part of the store. Also, the store is simply too
complex.

This commit splits the queue part out, using the new jobqueue package in both
the weldr and the rcm package. The queue is saved to a new directory `queue/`.

The weldr package now also has access to a worker server to enqueue and list
jobs. Its store continues to track composes, but the `QueueStatus` for each
compose (and image build) is deprecated. The field in `ImageBuild` is kept for
backwards compatibility for composes which finished before this change, but a
lot of code dealing with it in package compose is dropped.

store.PushCompose() is degraded to storing a new compose. It should probably be
renamed in the future. store.PopJob() is removed.

Job ids are now independent of compose ids. Because of that, the local
target gains ComposeId and ImageBuildId fields, because a worker cannot
infer those from a job anymore. This also necessitates a change in the
worker API: the job routes are changed to expect that instead of a
(compose id, image build id) pair. The route that accepts built images
keeps that pair, because it reports the image back to weldr.

worker.Server() now interacts with a job queue instead of the store. It gains
public functions that allow enqueuing an osbuild job and getting its status,
because only it knows about the specific argument and result types in the job
queue (OSBuildJob and OSBuildJobResult). One oddity remains: it needs to report
an uploaded image to weldr. Do this with a function that's passed in for now,
so that the dependency to the store can be dropped completely.

The rcm API drops its dependencies to package blueprint and store, because it
too interacts only with the worker server now.

Fixes #342
2020-05-08 14:53:00 +02:00
Lars Karlitski
4a710429de worker: rename API to Server
This makes it symmetric with the client:

    s := worker.NewServer()
    c := worker.NewClient()
2020-04-16 01:02:16 +02:00
Renamed from internal/worker/api.go (Browse further)