Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cloupapi/v2: add koji support #2214

Merged
merged 11 commits into from
Feb 1, 2022
4 changes: 3 additions & 1 deletion cmd/osbuild-worker/jobimpl-koji-finalize.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,9 @@ func hasFailedDependency(kojiInitResult worker.KojiInitJobResult, osbuildKojiRes
}

for _, r := range osbuildKojiResults {
if !r.OSBuildOutput.Success || r.JobError != nil {
// No `OSBuildOutput` implies failure: either osbuild crashed or
// rejected the input (manifest or command line arguments)
if r.OSBuildOutput == nil || !r.OSBuildOutput.Success || r.JobError != nil {
return true
}
}
Expand Down
23 changes: 23 additions & 0 deletions cmd/osbuild-worker/jobimpl-osbuild-koji.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,29 @@ func (impl *OSBuildKojiJobImpl) Run(job worker.Job) error {
return err
}

// In case the manifest is empty, try to get it from dynamic args
if len(args.Manifest) == 0 {
if job.NDynamicArgs() > 1 {
var manifestJR worker.ManifestJobByIDResult
err = job.DynamicArgs(1, &manifestJR)
if err != nil {
return err
}

// skip the job if the manifest generation failed
if manifestJR.JobError != nil {
result.JobError = clienterrors.WorkerClientError(clienterrors.ErrorManifestDependency, "Manifest dependency failed")
return nil
}
args.Manifest = manifestJR.Manifest
if len(args.Manifest) == 0 {
return fmt.Errorf("received empty manifest")
}
} else {
return fmt.Errorf("job has no manifest")
}
}

if initArgs.JobError == nil {
exports := args.Exports
if len(exports) == 0 {
Expand Down
4 changes: 2 additions & 2 deletions cmd/osbuild-worker/osbuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ func RunOSBuild(manifest distro.Manifest, store, outputDirectory string, exports
return nil, fmt.Errorf("error starting osbuild: %v", err)
}

err = json.NewEncoder(stdin).Encode(manifest)
_, err = stdin.Write(manifest)
if err != nil {
return nil, fmt.Errorf("error encoding osbuild pipeline: %v", err)
return nil, fmt.Errorf("error writing osbuild manifest: %v", err)
}

err = stdin.Close()
Expand Down
6 changes: 6 additions & 0 deletions internal/cloudapi/v2/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ const (
ErrorMethodNotAllowed ServiceErrorCode = 22
ErrorNotAcceptable ServiceErrorCode = 23
ErrorNoBaseURLInPayloadRepository ServiceErrorCode = 24
ErrorInvalidNumberOfImageBuilds ServiceErrorCode = 25
ErrorInvalidJobType ServiceErrorCode = 26

// Internal errors, these are bugs
ErrorFailedToInitializeBlueprint ServiceErrorCode = 1000
Expand All @@ -54,6 +56,7 @@ const (
ErrorMalformedOSBuildJobResult ServiceErrorCode = 1012
ErrorGettingDepsolveJobStatus ServiceErrorCode = 1013
ErrorDepsolveJobCanceled ServiceErrorCode = 1014
ErrorUnexpectedNumberOfImageBuilds ServiceErrorCode = 1015

// Errors contained within this file
ErrorUnspecified ServiceErrorCode = 10000
Expand Down Expand Up @@ -97,6 +100,8 @@ func getServiceErrors() serviceErrors {
serviceError{ErrorMethodNotAllowed, http.StatusMethodNotAllowed, "Requested method isn't supported for resource"},
serviceError{ErrorNotAcceptable, http.StatusNotAcceptable, "Only 'application/json' content is supported"},
serviceError{ErrorNoBaseURLInPayloadRepository, http.StatusBadRequest, "BaseURL must be specified for payload repositories"},
serviceError{ErrorInvalidJobType, http.StatusNotFound, "Requested job has invalid type"},
serviceError{ErrorInvalidNumberOfImageBuilds, http.StatusBadRequest, "Compose request has unsupported number of image builds"},

serviceError{ErrorFailedToInitializeBlueprint, http.StatusInternalServerError, "Failed to initialize blueprint"},
serviceError{ErrorFailedToGenerateManifestSeed, http.StatusInternalServerError, "Failed to generate manifest seed"},
Expand All @@ -113,6 +118,7 @@ func getServiceErrors() serviceErrors {
serviceError{ErrorMalformedOSBuildJobResult, http.StatusInternalServerError, "OSBuildJobResult does not have expected fields set"},
serviceError{ErrorGettingDepsolveJobStatus, http.StatusInternalServerError, "Unable to get depsolve job status"},
serviceError{ErrorDepsolveJobCanceled, http.StatusInternalServerError, "Depsolve job was cancelled"},
serviceError{ErrorUnexpectedNumberOfImageBuilds, http.StatusInternalServerError, "Compose has unexpected number of image builds"},

serviceError{ErrorUnspecified, http.StatusInternalServerError, "Unspecified internal error "},
serviceError{ErrorNotHTTPError, http.StatusInternalServerError, "Error is not an instance of HTTPError"},
Expand Down
236 changes: 169 additions & 67 deletions internal/cloudapi/v2/openapi.v2.gen.go

Large diffs are not rendered by default.

150 changes: 147 additions & 3 deletions internal/cloudapi/v2/openapi.v2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,72 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Error'
'/composes/{id}/logs':
get:
operationId: getComposeLogs
summary: Get logs for a compose.
parameters:
- in: path
name: id
schema:
type: string
format: uuid
example: 123e4567-e89b-12d3-a456-426655440000
required: true
description: ID of compose status to get
description: 'Get the status of a running or finished compose. This includes whether or not it succeeded, and also meta information about the result.'
responses:
'200':
description: The logs for the given compose, in no particular format (though valid JSON).
content:
application/json:
schema:
$ref: '#/components/schemas/ComposeLogs'
'400':
description: Invalid compose id
content:
text/plain:
schema:
type: string
'404':
description: Unknown compose id
content:
text/plain:
schema:
type: string
'/composes/{id}/manifests':
get:
operationId: getComposeManifests
summary: Get the manifests for a compose.
parameters:
- in: path
name: id
schema:
type: string
format: uuid
example: 123e4567-e89b-12d3-a456-426655440000
required: true
description: ID of compose status to get
description: 'Get the manifests of a running or finished compose. Returns one manifest for each image in the request. Each manifest conforms to the format defined at https://www.osbuild.org/man/osbuild-manifest.5'
responses:
'200':
description: The manifest for the given compose.
content:
application/json:
schema:
$ref: '#/components/schemas/ComposeManifests'
'400':
description: Invalid compose id
content:
text/plain:
schema:
type: string
'404':
description: Unknown compose id
content:
text/plain:
schema:
type: string

/compose:
post:
Expand Down Expand Up @@ -350,10 +416,54 @@ components:
- $ref: '#/components/schemas/ObjectReference'
- type: object
required:
- status
- image_status
teg marked this conversation as resolved.
Show resolved Hide resolved
properties:
status:
$ref: '#/components/schemas/ComposeStatusValue'
image_status:
$ref: '#/components/schemas/ImageStatus'
image_statuses:
type: array
items:
$ref: '#/components/schemas/ImageStatus'
koji_status:
$ref: '#/components/schemas/KojiStatus'
ComposeStatusValue:
type: string
enum:
- success
- failure
- pending
example: success
ComposeLogs:
allOf:
- $ref: '#/components/schemas/ObjectReference'
- type: object
required:
- image_builds
properties:
image_builds:
type: array
koji:
$ref: '#/components/schemas/KojiLogs'
KojiLogs:
type: object
required:
- init
- import
properties:
init: {}
import: {}
ComposeManifests:
allOf:
- $ref: '#/components/schemas/ObjectReference'
- type: object
required:
- manifests
properties:
manifests:
type: array
ImageStatus:
required:
- status
Expand Down Expand Up @@ -430,6 +540,12 @@ components:
image_name:
type: string
example: 'my-image'
KojiStatus:
type: object
properties:
build_id:
type: integer
example: 42

ComposeMetadata:
allOf:
Expand Down Expand Up @@ -473,21 +589,25 @@ components:
ComposeRequest:
required:
- distribution
- image_request
properties:
distribution:
type: string
example: 'rhel-8'
image_request:
$ref: '#/components/schemas/ImageRequest'
image_requests:
type: array
items:
$ref: '#/components/schemas/ImageRequest'
customizations:
$ref: '#/components/schemas/Customizations'
koji:
$ref: '#/components/schemas/Koji'
ImageRequest:
required:
- architecture
- image_type
- repositories
- upload_options
properties:
architecture:
type: string
Expand Down Expand Up @@ -733,7 +853,31 @@ components:
key:
type: string
example: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINrGKErMYi+MMUwuHaRAJmRLoIzRf2qD2dD5z0BTx/6x"

Koji:
type: object
required:
- server
- task_id
- name
- version
- release
properties:
server:
type: string
format: url
example: 'https://koji.fedoraproject.org/kojihub'
task_id:
type: integer
example: 42
name:
type: string
example: Fedora-Cloud-Base
version:
type: string
example: '31'
release:
type: string
example: '20200907.0'
ComposeId:
allOf:
- $ref: '#/components/schemas/ObjectReference'
Expand Down
Loading