diff --git a/cmd/osbuild-worker/jobimpl-osbuild.go b/cmd/osbuild-worker/jobimpl-osbuild.go index 358d6ffe0..a8041030c 100644 --- a/cmd/osbuild-worker/jobimpl-osbuild.go +++ b/cmd/osbuild-worker/jobimpl-osbuild.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "math" "math/big" + "net/url" "os" "path" "strings" @@ -38,14 +39,15 @@ type S3Configuration struct { } type OSBuildJobImpl struct { - Store string - Output string - KojiServers map[string]koji.GSSAPICredentials - GCPCreds string - AzureCreds *azure.Credentials - AWSCreds string - AWSBucket string - S3Config S3Configuration + Store string + Output string + KojiServers map[string]koji.GSSAPICredentials + KojiRelaxTimeoutFactor uint + GCPCreds string + AzureCreds *azure.Credentials + AWSCreds string + AWSBucket string + S3Config S3Configuration } // Returns an *awscloud.AWS object with the credentials of the request. If they @@ -692,6 +694,54 @@ func (impl *OSBuildJobImpl) Run(job worker.Job) error { ImageName: args.Targets[0].ImageName, })) + osbuildJobResult.Success = true + osbuildJobResult.UploadStatus = "success" + case *target.KojiTargetOptions: + kojiServerURL, err := url.Parse(options.Server) + if err != nil { + osbuildJobResult.JobError = clienterrors.WorkerClientError(clienterrors.ErrorInvalidTargetConfig, fmt.Sprintf("failed to parse Koji server URL: %v", err)) + return nil + } + + creds, exists := impl.KojiServers[kojiServerURL.Hostname()] + if !exists { + osbuildJobResult.JobError = clienterrors.WorkerClientError(clienterrors.ErrorInvalidTargetConfig, fmt.Sprintf("Koji server has not been configured: %s", kojiServerURL.Hostname())) + return nil + } + + kojiTransport := koji.CreateKojiTransport(impl.KojiRelaxTimeoutFactor) + + kojiAPI, err := koji.NewFromGSSAPI(options.Server, &creds, kojiTransport) + if err != nil { + osbuildJobResult.JobError = clienterrors.WorkerClientError(clienterrors.ErrorInvalidTargetConfig, fmt.Sprintf("failed to authenticate with Koji server %q: %v", kojiServerURL.Hostname(), err)) + return nil + } + logWithId.Infof("[Koji] 🔑 Authenticated with %q", kojiServerURL.Hostname()) + defer func() { + err := kojiAPI.Logout() + if err != nil { + logWithId.Warnf("[Koji] logout failed: %v", err) + } + }() + file, err := os.Open(path.Join(outputDirectory, exportPath, args.ImageName)) + if err != nil { + osbuildJobResult.JobError = clienterrors.WorkerClientError(clienterrors.ErrorKojiBuild, fmt.Sprintf("failed to open the image for reading: %v", err)) + return nil + } + defer file.Close() + + logWithId.Info("[Koji] ⬆ Uploading the image") + imageHash, imageSize, err := kojiAPI.Upload(file, options.UploadDirectory, options.Filename) + if err != nil { + osbuildJobResult.JobError = clienterrors.WorkerClientError(clienterrors.ErrorUploadingImage, err.Error()) + } + logWithId.Info("[Koji] 🎉 Image successfully uploaded") + + osbuildJobResult.TargetResults = append(osbuildJobResult.TargetResults, target.NewKojiTargetResult(&target.KojiTargetResultOptions{ + ImageMD5: imageHash, + ImageSize: imageSize, + })) + osbuildJobResult.Success = true osbuildJobResult.UploadStatus = "success" case *target.OCITargetOptions: diff --git a/cmd/osbuild-worker/main.go b/cmd/osbuild-worker/main.go index a3e029f90..4f266447e 100644 --- a/cmd/osbuild-worker/main.go +++ b/cmd/osbuild-worker/main.go @@ -227,7 +227,7 @@ func main() { ClientId string `toml:"client_id"` ClientSecretPath string `toml:"client_secret"` } `toml:"authentication"` - RelaxTimeoutFactor uint `toml:"RelaxTimeoutFactor"` + RelaxTimeoutFactor uint `toml:"RelaxTimeoutFactor"` // Should be moved under 'koji' section BasePath string `toml:"base_path"` DNFJson string `toml:"dnf-json"` } @@ -449,13 +449,14 @@ func main() { // non-depsolve job jobImpls := map[string]JobImplementation{ "osbuild": &OSBuildJobImpl{ - Store: store, - Output: output, - KojiServers: kojiServers, - GCPCreds: gcpCredentials, - AzureCreds: azureCredentials, - AWSCreds: awsCredentials, - AWSBucket: awsBucket, + Store: store, + Output: output, + KojiServers: kojiServers, + KojiRelaxTimeoutFactor: config.RelaxTimeoutFactor, + GCPCreds: gcpCredentials, + AzureCreds: azureCredentials, + AWSCreds: awsCredentials, + AWSBucket: awsBucket, S3Config: S3Configuration{ Creds: genericS3Credentials, Endpoint: genericS3Endpoint, diff --git a/internal/target/targetresult.go b/internal/target/targetresult.go index f1f143968..971f9c443 100644 --- a/internal/target/targetresult.go +++ b/internal/target/targetresult.go @@ -53,6 +53,8 @@ func UnmarshalTargetResultOptions(trName string, rawOptions json.RawMessage) (Ta options = new(GCPTargetResultOptions) case "org.osbuild.azure.image": options = new(AzureImageTargetResultOptions) + case "org.osbuild.koji": + options = new(KojiTargetResultOptions) case "org.osbuild.oci": options = new(OCITargetResultOptions) default: