Blame internal/worker/client.go

Packit 63bb0d
package worker
Packit 63bb0d
Packit 63bb0d
import (
Packit 63bb0d
	"bytes"
Packit 63bb0d
	"context"
Packit 63bb0d
	"crypto/tls"
Packit 63bb0d
	"encoding/json"
Packit 63bb0d
	"errors"
Packit 63bb0d
	"fmt"
Packit 63bb0d
	"io"
Packit 63bb0d
	"net"
Packit 63bb0d
	"net/http"
Packit 63bb0d
Packit 63bb0d
	"github.com/google/uuid"
Packit 63bb0d
Packit 63bb0d
	"github.com/osbuild/osbuild-composer/internal/common"
Packit 63bb0d
	"github.com/osbuild/osbuild-composer/internal/distro"
Packit 63bb0d
	"github.com/osbuild/osbuild-composer/internal/target"
Packit 63bb0d
)
Packit 63bb0d
Packit 63bb0d
type Client struct {
Packit 63bb0d
	client   *http.Client
Packit 63bb0d
	scheme   string
Packit 63bb0d
	hostname string
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
type Job struct {
Packit 63bb0d
	Id       uuid.UUID
Packit 63bb0d
	Manifest distro.Manifest
Packit 63bb0d
	Targets  []*target.Target
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func NewClient(address string, conf *tls.Config) *Client {
Packit 63bb0d
	client := &http.Client{
Packit 63bb0d
		Transport: &http.Transport{
Packit 63bb0d
			TLSClientConfig: conf,
Packit 63bb0d
		},
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	var scheme string
Packit 63bb0d
	// Use https if the TLS configuration is present, otherwise use http.
Packit 63bb0d
	if conf != nil {
Packit 63bb0d
		scheme = "https"
Packit 63bb0d
	} else {
Packit 63bb0d
		scheme = "http"
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return &Client{client, scheme, address}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func NewClientUnix(path string) *Client {
Packit 63bb0d
	client := &http.Client{
Packit 63bb0d
		Transport: &http.Transport{
Packit 63bb0d
			DialContext: func(context context.Context, network, addr string) (net.Conn, error) {
Packit 63bb0d
				return net.Dial("unix", path)
Packit 63bb0d
			},
Packit 63bb0d
		},
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return &Client{client, "http", "localhost"}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (c *Client) AddJob() (*Job, error) {
Packit 63bb0d
	var b bytes.Buffer
Packit 63bb0d
	err := json.NewEncoder(&b).Encode(addJobRequest{})
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		panic(err)
Packit 63bb0d
	}
Packit 63bb0d
	response, err := c.client.Post(c.createURL("/job-queue/v1/jobs"), "application/json", &b)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
	defer response.Body.Close()
Packit 63bb0d
Packit 63bb0d
	if response.StatusCode != http.StatusCreated {
Packit 63bb0d
		var er errorResponse
Packit 63bb0d
		_ = json.NewDecoder(response.Body).Decode(&er)
Packit 63bb0d
		return nil, fmt.Errorf("couldn't create job, got %d: %s", response.StatusCode, er.Message)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	var jr addJobResponse
Packit 63bb0d
	err = json.NewDecoder(response.Body).Decode(&jr)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return nil, err
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return &Job{
Packit 63bb0d
		jr.Id,
Packit 63bb0d
		jr.Manifest,
Packit 63bb0d
		jr.Targets,
Packit 63bb0d
	}, nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (c *Client) JobCanceled(job *Job) bool {
Packit 63bb0d
	response, err := c.client.Get(c.createURL("/job-queue/v1/jobs/" + job.Id.String()))
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return true
Packit 63bb0d
	}
Packit 63bb0d
	defer response.Body.Close()
Packit 63bb0d
Packit 63bb0d
	if response.StatusCode != http.StatusOK {
Packit 63bb0d
		return true
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	var jr jobResponse
Packit 63bb0d
	err = json.NewDecoder(response.Body).Decode(&jr)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return true
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return jr.Canceled
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (c *Client) UpdateJob(job *Job, status common.ImageBuildState, result *common.ComposeResult) error {
Packit 63bb0d
	var b bytes.Buffer
Packit 63bb0d
	err := json.NewEncoder(&b).Encode(&updateJobRequest{status, result})
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		panic(err)
Packit 63bb0d
	}
Packit 63bb0d
	urlPath := fmt.Sprintf("/job-queue/v1/jobs/%s", job.Id)
Packit 63bb0d
	url := c.createURL(urlPath)
Packit 63bb0d
	req, err := http.NewRequest("PATCH", url, &b)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return err
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	req.Header.Set("Content-Type", "application/json")
Packit 63bb0d
	response, err := c.client.Do(req)
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		return err
Packit 63bb0d
	}
Packit 63bb0d
	defer response.Body.Close()
Packit 63bb0d
Packit 63bb0d
	if response.StatusCode != http.StatusOK {
Packit 63bb0d
		return errors.New("error setting job status")
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return nil
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (c *Client) UploadImage(job uuid.UUID, name string, reader io.Reader) error {
Packit 63bb0d
	url := c.createURL(fmt.Sprintf("/job-queue/v1/jobs/%s/artifacts/%s", job, name))
Packit 63bb0d
	_, err := c.client.Post(url, "application/octet-stream", reader)
Packit 63bb0d
Packit 63bb0d
	return err
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (c *Client) createURL(path string) string {
Packit 63bb0d
	return c.scheme + "://" + c.hostname + path
Packit 63bb0d
}