As a part of f4991cb1 ComposeEntry struct was removed from store package.
This change made sense because this struct is connected more with API than
with store - store uses its own Compose struct. In addition, converters
between Compose and ComposeEntry were added. Unfortunately, ComposeEntry
contains ImageSize which was not stored in Compose but retrieved from store
using GetImage method. This made those converters dependent on the store,
which was messy.
To solve this issue this commit adds image struct into Compose struct.
The content of image struct is generated on the worker side - when the worker
sets the compose status to FINISHED, it also sends Image struct with detailed
information about the result.
115 lines
2.3 KiB
Go
115 lines
2.3 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"net/http"
|
|
|
|
"github.com/osbuild/osbuild-composer/internal/distro"
|
|
"github.com/osbuild/osbuild-composer/internal/jobqueue"
|
|
"github.com/osbuild/osbuild-composer/internal/store"
|
|
)
|
|
|
|
type ComposerClient struct {
|
|
client *http.Client
|
|
}
|
|
|
|
func NewClient() *ComposerClient {
|
|
client := &http.Client{
|
|
Transport: &http.Transport{
|
|
DialContext: func(context context.Context, network, addr string) (net.Conn, error) {
|
|
return net.Dial("unix", "/run/osbuild-composer/job.socket")
|
|
},
|
|
},
|
|
}
|
|
return &ComposerClient{client}
|
|
}
|
|
|
|
func (c *ComposerClient) AddJob() (*jobqueue.Job, error) {
|
|
type request struct {
|
|
}
|
|
|
|
var b bytes.Buffer
|
|
json.NewEncoder(&b).Encode(request{})
|
|
response, err := c.client.Post("http://localhost/job-queue/v1/jobs", "application/json", &b)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusCreated {
|
|
return nil, errors.New("couldn't create job")
|
|
}
|
|
|
|
job := &jobqueue.Job{}
|
|
err = json.NewDecoder(response.Body).Decode(job)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return job, nil
|
|
}
|
|
|
|
func (c *ComposerClient) UpdateJob(job *jobqueue.Job, status string, image *store.Image) error {
|
|
var b bytes.Buffer
|
|
json.NewEncoder(&b).Encode(&jobqueue.JobStatus{status, image})
|
|
req, err := http.NewRequest("PATCH", "http://localhost/job-queue/v1/jobs/"+job.ID.String(), &b)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
response, err := c.client.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
if response.StatusCode != http.StatusOK {
|
|
return errors.New("error setting job status")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func handleJob(client *ComposerClient, distro distro.Distro) {
|
|
fmt.Println("Waiting for a new job...")
|
|
job, err := client.AddJob()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
client.UpdateJob(job, "RUNNING", nil)
|
|
|
|
fmt.Printf("Running job %s\n", job.ID.String())
|
|
image, err, errs := job.Run(distro)
|
|
if err != nil {
|
|
client.UpdateJob(job, "FAILED", nil)
|
|
return
|
|
}
|
|
|
|
for _, err := range errs {
|
|
if err != nil {
|
|
client.UpdateJob(job, "FAILED", nil)
|
|
return
|
|
}
|
|
}
|
|
|
|
client.UpdateJob(job, "FINISHED", image)
|
|
}
|
|
|
|
func main() {
|
|
distro, err := distro.FromHost()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
client := NewClient()
|
|
for {
|
|
handleJob(client, distro)
|
|
}
|
|
}
|