diff --git a/internal/cloudapi/v2/handler.go b/internal/cloudapi/v2/handler.go index 9eb0c774d..111f99717 100644 --- a/internal/cloudapi/v2/handler.go +++ b/internal/cloudapi/v2/handler.go @@ -299,10 +299,6 @@ func (h *apiHandlers) PostCompose(ctx echo.Context) error { return HTTPError(ErrorJSONUnMarshallingError) } } else { - // TODO: support uploads also for koji - if request.Koji != nil { - return HTTPError(ErrorJSONUnMarshallingError) - } /* oneOf is not supported by the openapi generator so marshal and unmarshal the uploadrequest based on the type */ switch ir.ImageType { case ImageTypesAws: @@ -516,6 +512,53 @@ func imageTypeFromApiImageType(it ImageTypes, arch distro.Arch) string { return "" } +func targetResultToUploadStatus(t *target.TargetResult) (*UploadStatus, error) { + var us *UploadStatus + var uploadType UploadTypes + var uploadOptions interface{} + + switch t.Name { + case target.TargetNameAWS: + uploadType = UploadTypesAws + awsOptions := t.Options.(*target.AWSTargetResultOptions) + uploadOptions = AWSEC2UploadStatus{ + Ami: awsOptions.Ami, + Region: awsOptions.Region, + } + case target.TargetNameAWSS3: + uploadType = UploadTypesAwsS3 + awsOptions := t.Options.(*target.AWSS3TargetResultOptions) + uploadOptions = AWSS3UploadStatus{ + Url: awsOptions.URL, + } + case target.TargetNameGCP: + uploadType = UploadTypesGcp + gcpOptions := t.Options.(*target.GCPTargetResultOptions) + uploadOptions = GCPUploadStatus{ + ImageName: gcpOptions.ImageName, + ProjectId: gcpOptions.ProjectID, + } + case target.TargetNameAzureImage: + uploadType = UploadTypesAzure + gcpOptions := t.Options.(*target.AzureImageTargetResultOptions) + uploadOptions = AzureUploadStatus{ + ImageName: gcpOptions.ImageName, + } + default: + return nil, fmt.Errorf("unknown upload target: %s", t.Name) + } + + us = &UploadStatus{ + // TODO: determine upload status based on the target results, not job results + // Don't set the status here for now, but let it be set by the caller. + //Status: UploadStatusValue(result.UploadStatus), + Type: uploadType, + Options: uploadOptions, + } + + return us, nil +} + func (h *apiHandlers) GetComposeStatus(ctx echo.Context, id string) error { return h.server.EnsureJobChannel(h.getComposeStatusImpl)(ctx, id) } @@ -549,47 +592,13 @@ func (h *apiHandlers) getComposeStatusImpl(ctx echo.Context, id string) error { if len(result.TargetResults) != 1 { return HTTPError(ErrorSeveralUploadTargets) } - tr := *result.TargetResults[0] - - var uploadType UploadTypes - var uploadOptions interface{} - - switch tr.Name { - case target.TargetNameAWS: - uploadType = UploadTypesAws - awsOptions := tr.Options.(*target.AWSTargetResultOptions) - uploadOptions = AWSEC2UploadStatus{ - Ami: awsOptions.Ami, - Region: awsOptions.Region, - } - case target.TargetNameAWSS3: - uploadType = UploadTypesAwsS3 - awsOptions := tr.Options.(*target.AWSS3TargetResultOptions) - uploadOptions = AWSS3UploadStatus{ - Url: awsOptions.URL, - } - case target.TargetNameGCP: - uploadType = UploadTypesGcp - gcpOptions := tr.Options.(*target.GCPTargetResultOptions) - uploadOptions = GCPUploadStatus{ - ImageName: gcpOptions.ImageName, - ProjectId: gcpOptions.ProjectID, - } - case target.TargetNameAzureImage: - uploadType = UploadTypesAzure - gcpOptions := tr.Options.(*target.AzureImageTargetResultOptions) - uploadOptions = AzureUploadStatus{ - ImageName: gcpOptions.ImageName, - } - default: + tr := result.TargetResults[0] + us, err = targetResultToUploadStatus(tr) + if err != nil { return HTTPError(ErrorUnknownUploadTarget) } - - us = &UploadStatus{ - Status: UploadStatusValue(result.UploadStatus), - Type: uploadType, - Options: uploadOptions, - } + // TODO: determine upload status based on the target results, not job results + us.Status = UploadStatusValue(result.UploadStatus) } return ctx.JSON(http.StatusOK, ComposeStatus{ @@ -631,10 +640,28 @@ func (h *apiHandlers) getComposeStatusImpl(ctx echo.Context, id string) error { if err != nil { return HTTPError(ErrorGettingBuildDependencyStatus) } + + var us *UploadStatus + // only single upload target in addition to Koji is allowed + if len(buildJobResult.TargetResults) > 2 { + return HTTPError(ErrorSeveralUploadTargets) + } + for _, tr := range buildJobResult.TargetResults { + if tr.Name != target.TargetNameKoji { + us, err = targetResultToUploadStatus(tr) + if err != nil { + return HTTPError(ErrorUnknownUploadTarget) + } + // TODO: determine upload status based on the target results, not job results + us.Status = UploadStatusValue(buildJobResult.UploadStatus) + } + } + buildJobResults = append(buildJobResults, buildJobResult) buildJobStatuses = append(buildJobStatuses, ImageStatus{ - Status: imageStatusFromKojiJobStatus(buildJobStatus, &initResult, &buildJobResult), - Error: composeStatusErrorFromJobError(buildJobError), + Status: imageStatusFromKojiJobStatus(buildJobStatus, &initResult, &buildJobResult), + Error: composeStatusErrorFromJobError(buildJobError), + UploadStatus: us, }) } response := ComposeStatus{ diff --git a/internal/cloudapi/v2/server.go b/internal/cloudapi/v2/server.go index b2ddba870..4d7a6671e 100644 --- a/internal/cloudapi/v2/server.go +++ b/internal/cloudapi/v2/server.go @@ -185,12 +185,18 @@ func (s *Server) enqueueKojiCompose(taskID uint64, server, name, version, releas kojiTarget.OsbuildArtifact.ExportName = ir.imageType.Exports()[0] kojiTarget.ImageName = kojiFilename + targets := []*target.Target{kojiTarget} + // add any cloud upload target if defined + if ir.target != nil { + targets = append(targets, ir.target) + } + buildID, err := s.workers.EnqueueOSBuildAsDependency(ir.arch.Name(), &worker.OSBuildJob{ PipelineNames: &worker.PipelineNames{ Build: ir.imageType.BuildPipelines(), Payload: ir.imageType.PayloadPipelines(), }, - Targets: []*target.Target{kojiTarget}, + Targets: targets, ManifestDynArgsIdx: common.IntToPtr(1), }, []uuid.UUID{initID, manifestJobID}, channel) if err != nil {