debian-forge-composer/internal/jobqueue/client.go
Lars Karlitski b5432e78b9 worker: move ComposerClient to jobqueue package
This moves the client code into the same package as the server code,
which makes it easier to change (and version) the two in sync. Also, it
will allow to make some structs private to the jobqueue package and to
test `Client`.

Also rename it to jobqueue.Client.
2020-03-25 14:05:44 +01:00

120 lines
2.5 KiB
Go

package jobqueue
import (
"bytes"
"context"
"crypto/tls"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"github.com/osbuild/osbuild-composer/internal/common"
)
type Client struct {
client *http.Client
scheme string
hostname string
}
func NewClient(address string, conf *tls.Config) *Client {
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: conf,
},
}
var scheme string
if conf != nil {
scheme = "http"
} else {
scheme = "https"
}
return &Client{client, scheme, address}
}
func NewClientUnix(path string) *Client {
client := &http.Client{
Transport: &http.Transport{
DialContext: func(context context.Context, network, addr string) (net.Conn, error) {
return net.Dial("unix", path)
},
},
}
return &Client{client, "http", "localhost"}
}
func (c *Client) AddJob() (*Job, error) {
type request struct {
}
var b bytes.Buffer
err := json.NewEncoder(&b).Encode(request{})
if err != nil {
panic(err)
}
response, err := c.client.Post(c.createURL("/job-queue/v1/jobs"), "application/json", &b)
if err != nil {
return nil, err
}
defer response.Body.Close()
if response.StatusCode != http.StatusCreated {
rawR, _ := ioutil.ReadAll(response.Body)
r := string(rawR)
return nil, fmt.Errorf("couldn't create job, got %d: %s", response.StatusCode, r)
}
job := &Job{}
err = json.NewDecoder(response.Body).Decode(job)
if err != nil {
return nil, err
}
return job, nil
}
func (c *Client) UpdateJob(job *Job, status common.ImageBuildState, result *common.ComposeResult) error {
var b bytes.Buffer
err := json.NewEncoder(&b).Encode(&JobStatus{status, result})
if err != nil {
panic(err)
}
urlPath := fmt.Sprintf("/job-queue/v1/jobs/%s/builds/%d", job.ID.String(), job.ImageBuildID)
url := c.createURL(urlPath)
req, err := http.NewRequest("PATCH", url, &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 (c *Client) UploadImage(job *Job, reader io.Reader) error {
// content type doesn't really matter
url := c.createURL(fmt.Sprintf("/job-queue/v1/jobs/%s/builds/%d/image", job.ID.String(), job.ImageBuildID))
_, err := c.client.Post(url, "application/octet-stream", reader)
return err
}
func (c *Client) createURL(path string) string {
return c.scheme + "://" + c.hostname + path
}