RHEL and Fedora used different output formats (.ami vs .raw.xz). The job package assumed `image.ami`, which failed for RHEL. Change Fedora to use image.raw.xz as well. This makes it consistent, but we should also get the filename from the distro at some point.
136 lines
2.8 KiB
Go
136 lines
2.8 KiB
Go
package jobqueue
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/osbuild/osbuild-composer/internal/distro"
|
|
"github.com/osbuild/osbuild-composer/internal/pipeline"
|
|
"github.com/osbuild/osbuild-composer/internal/target"
|
|
"github.com/osbuild/osbuild-composer/internal/upload/awsupload"
|
|
)
|
|
|
|
type Job struct {
|
|
ID uuid.UUID `json:"id"`
|
|
Pipeline *pipeline.Pipeline `json:"pipeline"`
|
|
Targets []*target.Target `json:"targets"`
|
|
}
|
|
|
|
type JobStatus struct {
|
|
Status string `json:"status"`
|
|
}
|
|
|
|
func (job *Job) Run(d distro.Distro) (error, []error) {
|
|
build := pipeline.Build{
|
|
Runner: d.Runner(),
|
|
}
|
|
|
|
buildFile, err := ioutil.TempFile("", "osbuild-worker-build-env-*")
|
|
if err != nil {
|
|
return err, nil
|
|
}
|
|
defer os.Remove(buildFile.Name())
|
|
|
|
err = json.NewEncoder(buildFile).Encode(build)
|
|
if err != nil {
|
|
return err, nil
|
|
}
|
|
|
|
cmd := exec.Command(
|
|
"osbuild",
|
|
"--store", "/var/cache/osbuild-composer/store",
|
|
"--build-env", buildFile.Name(),
|
|
"--json", "-",
|
|
)
|
|
cmd.Stderr = os.Stderr
|
|
|
|
stdin, err := cmd.StdinPipe()
|
|
if err != nil {
|
|
return err, nil
|
|
}
|
|
|
|
stdout, err := cmd.StdoutPipe()
|
|
if err != nil {
|
|
return err, nil
|
|
}
|
|
|
|
err = cmd.Start()
|
|
if err != nil {
|
|
return err, nil
|
|
}
|
|
|
|
err = json.NewEncoder(stdin).Encode(job.Pipeline)
|
|
if err != nil {
|
|
return err, nil
|
|
}
|
|
stdin.Close()
|
|
|
|
var result struct {
|
|
TreeID string `json:"tree_id"`
|
|
OutputID string `json:"output_id"`
|
|
}
|
|
err = json.NewDecoder(stdout).Decode(&result)
|
|
if err != nil {
|
|
return err, nil
|
|
}
|
|
|
|
err = cmd.Wait()
|
|
if err != nil {
|
|
return err, nil
|
|
}
|
|
|
|
var r []error
|
|
|
|
for _, t := range job.Targets {
|
|
switch options := t.Options.(type) {
|
|
case *target.LocalTargetOptions:
|
|
err = os.MkdirAll(options.Location, 0755)
|
|
if err != nil {
|
|
r = append(r, err)
|
|
continue
|
|
}
|
|
|
|
cp := exec.Command("cp", "-a", "-L", "/var/cache/osbuild-composer/store/refs/"+result.OutputID+"/.", options.Location)
|
|
cp.Stderr = os.Stderr
|
|
cp.Stdout = os.Stdout
|
|
err = cp.Run()
|
|
if err != nil {
|
|
r = append(r, err)
|
|
continue
|
|
}
|
|
case *target.AWSTargetOptions:
|
|
a, err := awsupload.New(options.Region, options.AccessKeyID, options.SecretAccessKey)
|
|
if err != nil {
|
|
r = append(r, err)
|
|
continue
|
|
}
|
|
|
|
if options.Key == "" {
|
|
options.Key = job.ID.String()
|
|
}
|
|
|
|
_, err = a.Upload("/var/cache/osbuild-composer/store/refs/"+result.OutputID+"/image.raw.xz", options.Bucket, options.Key)
|
|
if err != nil {
|
|
r = append(r, err)
|
|
continue
|
|
}
|
|
|
|
/* TODO: communicate back the AMI */
|
|
_, err = a.Register(t.ImageName, options.Bucket, options.Key)
|
|
if err != nil {
|
|
r = append(r, err)
|
|
continue
|
|
}
|
|
case *target.AzureTargetOptions:
|
|
default:
|
|
r = append(r, fmt.Errorf("invalid target type"))
|
|
}
|
|
r = append(r, nil)
|
|
}
|
|
|
|
return nil, r
|
|
}
|