debian-forge-composer/cmd/osbuild-worker/main.go
Tom Gundersen 118b185fdd osbuild-{composer/worker}: exit cleanly
Only panic on compile-time errors (e.g., built for unsupported
architecture). Otherwise, use log.Fatalf(), which is equivalent to
printing and exiting with return code 1. Only ever do this from
main(), in all other cases pass on the error object.

This is mostly relevant when the server disconects, in which case
we'll get EOF, and will now restart cleanly instead of panicing.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2019-12-11 15:23:24 +01:00

118 lines
2.5 KiB
Go

package main
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"log"
"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) error {
fmt.Println("Waiting for a new job...")
job, err := client.AddJob()
if err != nil {
return err
}
err = client.UpdateJob(job, "RUNNING", nil)
if err != nil {
return err
}
fmt.Printf("Running job %s\n", job.ID.String())
image, err, errs := job.Run(distro)
if err != nil {
return client.UpdateJob(job, "FAILED", nil)
}
for _, err := range errs {
if err != nil {
return client.UpdateJob(job, "FAILED", nil)
}
}
return client.UpdateJob(job, "FINISHED", image)
}
func main() {
distro, err := distro.FromHost()
if err != nil {
log.Fatalf("Could not determine distro from host: " + err.Error())
}
client := NewClient()
for {
err = handleJob(client, distro)
log.Fatalf("Failed to handle job: " + err.Error())
}
}