Skip to content

Commit

Permalink
bib/composer integration: add manifest job for osbuild processing
Browse files Browse the repository at this point in the history
With this change:
- Bib is used to generate a manifest without initiating a full build.
- Composer’s osbuild job can now process the manifest independently.

This setup improves modularity and prepares for future enhancements in the osbuild processing pipeline.
  • Loading branch information
amirfefer committed Oct 30, 2024
1 parent 4afcd8c commit 877debe
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 0 deletions.
126 changes: 126 additions & 0 deletions cmd/osbuild-worker/jobimpl-bootc-manifest.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package main

import (
"encoding/json"
"fmt"
"os/exec"
"regexp"

"github.com/sirupsen/logrus"

"github.com/osbuild/images/pkg/manifest"
"github.com/osbuild/osbuild-composer/internal/worker"
"github.com/osbuild/osbuild-composer/internal/worker/clienterrors"
)

type BootcManifestJobImpl struct{}

type ErrorInvalidImageType string

func (e ErrorInvalidImageType) Error() string { return string(e) }

type ErrorCommandExecution string

func (e ErrorCommandExecution) Error() string { return string(e) }

type ErrorInvalidArguments string

func (e ErrorInvalidArguments) Error() string { return string(e) }

type ErrorUnknown string

func (e ErrorUnknown) Error() string { return string(e) }

func setResponseError(err error, result *worker.BootcManifestJobResult) {
switch e := err.(type) {
case ErrorInvalidImageType:
result.JobError = clienterrors.New(
clienterrors.ErrorInvalidImageType,
"Unsupported image type",
e.Error(),
)
case ErrorCommandExecution:
result.JobError = clienterrors.New(
clienterrors.ErrorBootcManifestExec,
"Error running bootc-image-builder command",
e.Error(),
)
default:
result.JobError = clienterrors.New(
clienterrors.ErrorInvalidManifestArgs,
"Invalid bootc parameters or parameter combination",
err.Error(),
)
}
}

func buildManifestCommand(args *worker.BootcManifestJob) *exec.Cmd {
baseArgs := []string{
"sudo", "podman", "run",
"--privileged",
"--rm",
"--pull=missing",
"--storage-driver=vfs",
"--cgroup-manager=cgroupfs",
"--runtime=runc",
"--security-opt=label=type:unconfined_t",
"quay.io/centos-bootc/bootc-image-builder:latest",
"manifest",
args.ImageRef,
}

// Append optional arguments
if args.ImageType != "" {
baseArgs = append(baseArgs, "--type", args.ImageType)
}
if args.Arch != "" {
baseArgs = append(baseArgs, "--target-arch", args.Arch)
}
if !args.TLSVerify {
baseArgs = append(baseArgs, "--tls-verify=false")
}

return exec.Command(baseArgs[0], baseArgs[1:]...)

Check failure on line 83 in cmd/osbuild-worker/jobimpl-bootc-manifest.go

View workflow job for this annotation

GitHub Actions / ⌨ Golang Lint

G204: Subprocess launched with a potential tainted input or cmd arguments (gosec)
}

func (impl *BootcManifestJobImpl) Run(job worker.Job) error {
logrus.Info("Running bootc-image-builder job")
logWithId := logrus.WithField("jobId", job.Id())
// Parse the job arguments
var args worker.BootcManifestJob
err := job.Args(&args)
if err != nil {
return err
}
jobResult := worker.BootcManifestJobResult{}

cmd := buildManifestCommand(&args)
logWithId.Infof("Running bib manifest: %s", cmd.String())
output, err := cmd.CombinedOutput()
if err != nil {
logWithId.Errorf("Error running bootc-image-builder: %v, Output: %s", err, string(output))
setResponseError(ErrorCommandExecution(err.Error()), &jobResult)
return job.Update(&jobResult)
}

outputStr := string(output)
re := regexp.MustCompile(`\{.*\}`)
jsonData := re.FindString(outputStr)

var manifestData manifest.OSBuildManifest
err = json.Unmarshal([]byte(jsonData), &manifestData)
if err != nil {
logWithId.Errorf("Error unmarshalling manifest data: %v", err)
setResponseError(ErrorCommandExecution(err.Error()), &jobResult)
}

jobResult.Manifest = manifestData
jobResult.JobResult = worker.JobResult{}
err = job.Update(&jobResult)
if err != nil {
setResponseError(ErrorUnknown(fmt.Sprintf("Error reporting job result: %v", err)), &jobResult)
return job.Update(&jobResult)
}

return nil
}
3 changes: 3 additions & 0 deletions internal/worker/clienterrors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ const (
ErrorJobPanicked ClientErrorCode = 37
ErrorGeneratingSignedURL ClientErrorCode = 38
ErrorInvalidRepositoryURL ClientErrorCode = 39
ErrorBootcManifestExec ClientErrorCode = 40
ErrorInvalidImageType ClientErrorCode = 41
ErrorInvalidManifestArgs ClientErrorCode = 42
)

type ClientErrorCode int
Expand Down
13 changes: 13 additions & 0 deletions internal/worker/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,19 @@ type OSTreeResolveSpec struct {
RHSM bool `json:"rhsm"`
}

type BootcManifestJob struct {
ImageType string `json:"image_type"`
Arch string `json:"arch"`
ImageRef string `json:"image_ref"`
TLSVerify bool `json:"tls_verify,omitempty"`
}

type BootcManifestJobResult struct {
Manifest manifest.OSBuildManifest `json:"data,omitempty"`
Error string `json:"error"`
JobResult
}

type OSTreeResolveJob struct {
Specs []OSTreeResolveSpec `json:"ostree_resolve_specs"`
}
Expand Down
27 changes: 27 additions & 0 deletions internal/worker/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const (
JobTypeOSTreeResolve string = "ostree-resolve"
JobTypeAWSEC2Copy string = "aws-ec2-copy"
JobTypeAWSEC2Share string = "aws-ec2-share"
JobTypeBootcManifest string = "bootc-manifest"
)

type Server struct {
Expand Down Expand Up @@ -220,6 +221,10 @@ func (s *Server) EnqueueAWSEC2ShareJob(job *AWSEC2ShareJob, parent uuid.UUID, ch
return s.enqueue(JobTypeAWSEC2Share, job, []uuid.UUID{parent}, channel)
}

func (s *Server) EnqueueBootcManifestJob(job *BootcManifestJob, channel string) (uuid.UUID, error) {
return s.enqueue(JobTypeBootcManifest, job, nil, channel)
}

func (s *Server) enqueue(jobType string, job interface{}, dependencies []uuid.UUID, channel string) (uuid.UUID, error) {
prometheus.EnqueueJobMetrics(strings.Split(jobType, ":")[0], channel)
return s.jobs.Enqueue(jobType, job, dependencies, channel)
Expand Down Expand Up @@ -298,6 +303,10 @@ func (s *Server) JobDependencyChainErrors(id uuid.UUID) (*clienterrors.Error, er
}
jobResult = &ostreeResolveJR.JobResult

case JobTypeBootcManifest:
var bootcManifestJR BootcManifestJobResult
jobInfo, err = s.BootcManifestJobInfo(id, &bootcManifestJR)

Check failure on line 308 in internal/worker/server.go

View workflow job for this annotation

GitHub Actions / ⌨ Golang Lint

ineffectual assignment to err (ineffassign)

default:
return nil, fmt.Errorf("unexpected job type: %s", jobType)
}
Expand Down Expand Up @@ -489,6 +498,17 @@ func (s *Server) AWSEC2ShareJobInfo(id uuid.UUID, result *AWSEC2ShareJobResult)
return jobInfo, nil
}

func (s *Server) BootcManifestJobInfo(id uuid.UUID, result *BootcManifestJobResult) (*JobInfo, error) {
jobInfo, err := s.jobInfo(id, result)
if err != nil {
return nil, err
}
if jobInfo.JobType != JobTypeBootcManifest {
return nil, fmt.Errorf("expected %q, found %q job instead", JobTypeBootcManifest, jobInfo.JobType)
}
return jobInfo, nil
}

func (s *Server) jobInfo(id uuid.UUID, result interface{}) (*JobInfo, error) {
jobType, channel, rawResult, queued, started, finished, canceled, deps, dependents, err := s.jobs.JobStatus(id)
if err != nil {
Expand Down Expand Up @@ -802,6 +822,13 @@ func (s *Server) RequeueOrFinishJob(token uuid.UUID, maxRetries uint64, result j
return err
}
jobResult = &ostreeResolveJR.JobResult
case JobTypeBootcManifest:
var bootcManifestJR BootcManifestJobResult
jobInfo, err = s.BootcManifestJobInfo(jobId, &bootcManifestJR)
if err != nil {
return err
}
jobResult = &bootcManifestJR.JobResult

default:
return fmt.Errorf("unexpected job type: %s", jobType)
Expand Down

0 comments on commit 877debe

Please sign in to comment.