cloudapi: support container embedding
Add support for embedding container images via the cloud API. For this the container resolve job was plumbed into the cloud api's handler and the API specification updated with a new `containers` section that mimics the blueprint section with the same name.
This commit is contained in:
parent
45850639a0
commit
388154d7f6
7 changed files with 341 additions and 119 deletions
|
|
@ -31,6 +31,7 @@ const (
|
|||
ErrorTargetError ClientErrorCode = 28
|
||||
ErrorParsingJobArgs ClientErrorCode = 29
|
||||
ErrorContainerResolution ClientErrorCode = 30
|
||||
ErrorContainerDependency ClientErrorCode = 31
|
||||
)
|
||||
|
||||
type ClientErrorCode int
|
||||
|
|
@ -94,6 +95,8 @@ func GetStatusCode(err *Error) StatusCode {
|
|||
// IsDependencyError returns true if the error means that a dependency of a job failed
|
||||
func (e *Error) IsDependencyError() bool {
|
||||
switch e.ID {
|
||||
case ErrorContainerDependency:
|
||||
return true
|
||||
case ErrorDepsolveDependency:
|
||||
return true
|
||||
case ErrorManifestDependency:
|
||||
|
|
|
|||
|
|
@ -146,8 +146,11 @@ func (s *Server) EnqueueDepsolve(job *DepsolveJob, channel string) (uuid.UUID, e
|
|||
return s.enqueue(JobTypeDepsolve, job, nil, channel)
|
||||
}
|
||||
|
||||
func (s *Server) EnqueueManifestJobByID(job *ManifestJobByID, parent uuid.UUID, channel string) (uuid.UUID, error) {
|
||||
return s.enqueue(JobTypeManifestIDOnly, job, []uuid.UUID{parent}, channel)
|
||||
func (s *Server) EnqueueManifestJobByID(job *ManifestJobByID, dependencies []uuid.UUID, channel string) (uuid.UUID, error) {
|
||||
if len(dependencies) == 0 {
|
||||
panic("EnqueueManifestJobByID has no dependencies, expected at least a depsolve job")
|
||||
}
|
||||
return s.enqueue(JobTypeManifestIDOnly, job, dependencies, channel)
|
||||
}
|
||||
|
||||
func (s *Server) EnqueueContainerResolveJob(job *ContainerResolveJob, channel string) (uuid.UUID, error) {
|
||||
|
|
@ -622,6 +625,14 @@ func (s *Server) FinishJob(token uuid.UUID, result json.RawMessage) error {
|
|||
}
|
||||
jobResult = &kojiFinalizeJR.JobResult
|
||||
|
||||
case JobTypeContainerResolve:
|
||||
var containerResolveJR ContainerResolveJobResult
|
||||
jobInfo, err = s.ContainerResolveJobInfo(jobId, &containerResolveJR)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
jobResult = &containerResolveJR.JobResult
|
||||
|
||||
default:
|
||||
return fmt.Errorf("unexpected job type: %s", jobType)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -372,7 +372,7 @@ func TestRequestJobById(t *testing.T) {
|
|||
depsolveJobId, err := server.EnqueueDepsolve(&worker.DepsolveJob{}, "")
|
||||
require.NoError(t, err)
|
||||
|
||||
jobId, err := server.EnqueueManifestJobByID(&worker.ManifestJobByID{}, depsolveJobId, "")
|
||||
jobId, err := server.EnqueueManifestJobByID(&worker.ManifestJobByID{}, []uuid.UUID{depsolveJobId}, "")
|
||||
require.NoError(t, err)
|
||||
|
||||
test.TestRoute(t, server.Handler(), false, "POST", "/api/worker/v1/jobs", fmt.Sprintf(`{"arch":"arch","types":["%s"]}`, worker.JobTypeManifestIDOnly), http.StatusBadRequest,
|
||||
|
|
@ -742,10 +742,10 @@ func enqueueAndFinishTestJobDependencies(s *worker.Server, deps []testJob) ([]uu
|
|||
|
||||
case *worker.ManifestJobByID:
|
||||
job := dep.main.(*worker.ManifestJobByID)
|
||||
if len(depUUIDs) != 1 {
|
||||
return nil, fmt.Errorf("exactly one dependency is expected for ManifestJobByID, got: %d", len(depUUIDs))
|
||||
if len(depUUIDs) < 1 {
|
||||
return nil, fmt.Errorf("at least one dependency is expected for ManifestJobByID, got: %d", len(depUUIDs))
|
||||
}
|
||||
id, err = s.EnqueueManifestJobByID(job, depUUIDs[0], "")
|
||||
id, err = s.EnqueueManifestJobByID(job, depUUIDs, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -780,6 +780,16 @@ func enqueueAndFinishTestJobDependencies(s *worker.Server, deps []testJob) ([]uu
|
|||
return nil, err
|
||||
}
|
||||
|
||||
case *worker.ContainerResolveJob:
|
||||
job := dep.main.(*worker.ContainerResolveJob)
|
||||
if len(depUUIDs) != 0 {
|
||||
return nil, fmt.Errorf("dependencies are not supported for ContainerResolveJob, got: %d", len(depUUIDs))
|
||||
}
|
||||
id, err = s.EnqueueContainerResolveJob(job, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unexpected job type")
|
||||
}
|
||||
|
|
@ -942,6 +952,71 @@ func TestJobDependencyChainErrors(t *testing.T) {
|
|||
Reason: "empty manifest received",
|
||||
},
|
||||
},
|
||||
// osbuild + manifest + depsolve + container resolve
|
||||
// failed container resolve
|
||||
{
|
||||
job: testJob{
|
||||
main: &worker.OSBuildJob{},
|
||||
deps: []testJob{
|
||||
{
|
||||
main: &worker.KojiInitJob{},
|
||||
result: &worker.KojiInitJobResult{},
|
||||
},
|
||||
{
|
||||
main: &worker.ManifestJobByID{},
|
||||
deps: []testJob{
|
||||
{
|
||||
main: &worker.ContainerResolveJob{},
|
||||
result: &worker.ContainerResolveJobResult{
|
||||
JobResult: worker.JobResult{
|
||||
JobError: &clienterrors.Error{
|
||||
ID: clienterrors.ErrorContainerResolution,
|
||||
Reason: "remote container not found",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
main: &worker.DepsolveJob{},
|
||||
result: &worker.DepsolveJobResult{},
|
||||
},
|
||||
},
|
||||
result: &worker.ManifestJobByIDResult{
|
||||
JobResult: worker.JobResult{
|
||||
JobError: &clienterrors.Error{
|
||||
ID: clienterrors.ErrorContainerDependency,
|
||||
Reason: "container dependency job failed",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: &worker.OSBuildJobResult{
|
||||
JobResult: worker.JobResult{
|
||||
JobError: &clienterrors.Error{
|
||||
ID: clienterrors.ErrorManifestDependency,
|
||||
Reason: "manifest dependency job failed",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: &clienterrors.Error{
|
||||
ID: clienterrors.ErrorManifestDependency,
|
||||
Reason: "manifest dependency job failed",
|
||||
Details: []*clienterrors.Error{
|
||||
{
|
||||
ID: clienterrors.ErrorContainerDependency,
|
||||
Reason: "container dependency job failed",
|
||||
Details: []*clienterrors.Error{
|
||||
{
|
||||
ID: clienterrors.ErrorContainerResolution,
|
||||
Reason: "remote container not found",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// koji-init + osbuild + manifest + depsolve
|
||||
// failed depsolve
|
||||
{
|
||||
|
|
@ -1325,7 +1400,7 @@ func TestJobDependencyChainErrors(t *testing.T) {
|
|||
Reason: "koji-finalize failed",
|
||||
},
|
||||
},
|
||||
// koji-init + (osbuild + manifest + depsolve) + (osbuild + manifest + depsolve) + koji-finalize
|
||||
// koji-init + (osbuild + manifest + depsolve + container resolve) + (osbuild + manifest + depsolve) + koji-finalize
|
||||
// all passed
|
||||
{
|
||||
job: testJob{
|
||||
|
|
@ -1346,6 +1421,10 @@ func TestJobDependencyChainErrors(t *testing.T) {
|
|||
{
|
||||
main: &worker.ManifestJobByID{},
|
||||
deps: []testJob{
|
||||
{
|
||||
main: &worker.ContainerResolveJob{},
|
||||
result: &worker.ContainerResolveJobResult{},
|
||||
},
|
||||
{
|
||||
main: &worker.DepsolveJob{},
|
||||
result: &worker.DepsolveJobResult{},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue