|
Packit Service |
509fd4 |
package main
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
import (
|
|
Packit Service |
509fd4 |
"crypto/tls"
|
|
Packit Service |
509fd4 |
"fmt"
|
|
Packit Service |
509fd4 |
"log"
|
|
Packit Service |
509fd4 |
"net/http"
|
|
Packit Service |
509fd4 |
"net/url"
|
|
Packit Service |
509fd4 |
"time"
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
"github.com/osbuild/osbuild-composer/internal/upload/koji"
|
|
Packit Service |
509fd4 |
"github.com/osbuild/osbuild-composer/internal/worker"
|
|
Packit Service |
509fd4 |
)
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
type KojiFinalizeJobImpl struct {
|
|
Packit Service |
509fd4 |
KojiServers map[string]koji.GSSAPICredentials
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
func (impl *KojiFinalizeJobImpl) kojiImport(
|
|
Packit Service |
509fd4 |
server string,
|
|
Packit Service |
509fd4 |
build koji.ImageBuild,
|
|
Packit Service |
509fd4 |
buildRoots []koji.BuildRoot,
|
|
Packit Service |
509fd4 |
images []koji.Image,
|
|
Packit Service |
509fd4 |
directory, token string) error {
|
|
Packit Service |
509fd4 |
// Koji for some reason needs TLS renegotiation enabled.
|
|
Packit Service |
509fd4 |
// Clone the default http transport and enable renegotiation.
|
|
Packit Service |
509fd4 |
transport := http.DefaultTransport.(*http.Transport).Clone()
|
|
Packit Service |
509fd4 |
transport.TLSClientConfig = &tls.Config{
|
|
Packit Service |
509fd4 |
Renegotiation: tls.RenegotiateOnceAsClient,
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
serverURL, err := url.Parse(server)
|
|
Packit Service |
509fd4 |
if err != nil {
|
|
Packit Service |
509fd4 |
return err
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
creds, exists := impl.KojiServers[serverURL.Hostname()]
|
|
Packit Service |
509fd4 |
if !exists {
|
|
Packit Service |
509fd4 |
return fmt.Errorf("Koji server has not been configured: %s", serverURL.Hostname())
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
k, err := koji.NewFromGSSAPI(server, &creds, transport)
|
|
Packit Service |
509fd4 |
if err != nil {
|
|
Packit Service |
509fd4 |
return err
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
defer func() {
|
|
Packit Service |
509fd4 |
err := k.Logout()
|
|
Packit Service |
509fd4 |
if err != nil {
|
|
Packit Service |
509fd4 |
log.Printf("koji logout failed: %v", err)
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
}()
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
_, err = k.CGImport(build, buildRoots, images, directory, token)
|
|
Packit Service |
509fd4 |
if err != nil {
|
|
Packit Service |
509fd4 |
return fmt.Errorf("Could not import build into koji: %v", err)
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
return nil
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
func (impl *KojiFinalizeJobImpl) kojiFail(server string, buildID int, token string) error {
|
|
Packit Service |
509fd4 |
// Koji for some reason needs TLS renegotiation enabled.
|
|
Packit Service |
509fd4 |
// Clone the default http transport and enable renegotiation.
|
|
Packit Service |
509fd4 |
transport := http.DefaultTransport.(*http.Transport).Clone()
|
|
Packit Service |
509fd4 |
transport.TLSClientConfig = &tls.Config{
|
|
Packit Service |
509fd4 |
Renegotiation: tls.RenegotiateOnceAsClient,
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
serverURL, err := url.Parse(server)
|
|
Packit Service |
509fd4 |
if err != nil {
|
|
Packit Service |
509fd4 |
return err
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
creds, exists := impl.KojiServers[serverURL.Hostname()]
|
|
Packit Service |
509fd4 |
if !exists {
|
|
Packit Service |
509fd4 |
return fmt.Errorf("Koji server has not been configured: %s", serverURL.Hostname())
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
k, err := koji.NewFromGSSAPI(server, &creds, transport)
|
|
Packit Service |
509fd4 |
if err != nil {
|
|
Packit Service |
509fd4 |
return err
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
defer func() {
|
|
Packit Service |
509fd4 |
err := k.Logout()
|
|
Packit Service |
509fd4 |
if err != nil {
|
|
Packit Service |
509fd4 |
log.Printf("koji logout failed: %v", err)
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
}()
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
return k.CGFailBuild(buildID, token)
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
func (impl *KojiFinalizeJobImpl) Run(job worker.Job) error {
|
|
Packit Service |
509fd4 |
var args worker.KojiFinalizeJob
|
|
Packit Service |
509fd4 |
err := job.Args(&args)
|
|
Packit Service |
509fd4 |
if err != nil {
|
|
Packit Service |
509fd4 |
return err
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
initArgs, osbuildKojiResults, err := extractDynamicArgs(job)
|
|
Packit Service |
509fd4 |
if err != nil {
|
|
Packit Service |
509fd4 |
return err
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
// Check the dependencies early. Fail the koji build if any of them failed.
|
|
Packit Service |
509fd4 |
if hasFailedDependency(*initArgs, osbuildKojiResults) {
|
|
Packit Service |
509fd4 |
err = impl.kojiFail(args.Server, int(initArgs.BuildID), initArgs.Token)
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
// Update the status immediately and bail out.
|
|
Packit Service |
509fd4 |
var result worker.KojiFinalizeJobResult
|
|
Packit Service |
509fd4 |
if err != nil {
|
|
Packit Service |
509fd4 |
result.KojiError = err.Error()
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
err = job.Update(&result)
|
|
Packit Service |
509fd4 |
if err != nil {
|
|
Packit Service |
509fd4 |
return fmt.Errorf("Error reporting job result: %v", err)
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
return nil
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
build := koji.ImageBuild{
|
|
Packit Service |
509fd4 |
BuildID: initArgs.BuildID,
|
|
Packit Service |
509fd4 |
TaskID: args.TaskID,
|
|
Packit Service |
509fd4 |
Name: args.Name,
|
|
Packit Service |
509fd4 |
Version: args.Version,
|
|
Packit Service |
509fd4 |
Release: args.Release,
|
|
Packit Service |
509fd4 |
StartTime: int64(args.StartTime),
|
|
Packit Service |
509fd4 |
EndTime: time.Now().Unix(),
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
var buildRoots []koji.BuildRoot
|
|
Packit Service |
509fd4 |
var images []koji.Image
|
|
Packit Service |
509fd4 |
for i, buildArgs := range osbuildKojiResults {
|
|
Packit Service |
509fd4 |
buildRoots = append(buildRoots, koji.BuildRoot{
|
|
Packit Service |
509fd4 |
ID: uint64(i),
|
|
Packit Service |
509fd4 |
Host: koji.Host{
|
|
Packit Service |
509fd4 |
Os: buildArgs.HostOS,
|
|
Packit Service |
509fd4 |
Arch: buildArgs.Arch,
|
|
Packit Service |
509fd4 |
},
|
|
Packit Service |
509fd4 |
ContentGenerator: koji.ContentGenerator{
|
|
Packit Service |
509fd4 |
Name: "osbuild",
|
|
Packit Service |
509fd4 |
Version: "0", // TODO: put the correct version here
|
|
Packit Service |
509fd4 |
},
|
|
Packit Service |
509fd4 |
Container: koji.Container{
|
|
Packit Service |
509fd4 |
Type: "none",
|
|
Packit Service |
509fd4 |
Arch: buildArgs.Arch,
|
|
Packit Service |
509fd4 |
},
|
|
Packit Service |
509fd4 |
Tools: []koji.Tool{},
|
|
Packit Service |
509fd4 |
RPMs: osbuildStagesToRPMs(buildArgs.OSBuildOutput.Build.Stages),
|
|
Packit Service |
509fd4 |
})
|
|
Packit Service |
509fd4 |
images = append(images, koji.Image{
|
|
Packit Service |
509fd4 |
BuildRootID: uint64(i),
|
|
Packit Service |
509fd4 |
Filename: args.KojiFilenames[i],
|
|
Packit Service |
509fd4 |
FileSize: buildArgs.ImageSize,
|
|
Packit Service |
509fd4 |
Arch: buildArgs.Arch,
|
|
Packit Service |
509fd4 |
ChecksumType: "md5",
|
|
Packit Service |
509fd4 |
MD5: buildArgs.ImageHash,
|
|
Packit Service |
509fd4 |
Type: "image",
|
|
Packit Service |
509fd4 |
RPMs: osbuildStagesToRPMs(buildArgs.OSBuildOutput.Stages),
|
|
Packit Service |
509fd4 |
Extra: koji.ImageExtra{
|
|
Packit Service |
509fd4 |
Info: koji.ImageExtraInfo{
|
|
Packit Service |
509fd4 |
Arch: buildArgs.Arch,
|
|
Packit Service |
509fd4 |
},
|
|
Packit Service |
509fd4 |
},
|
|
Packit Service |
509fd4 |
})
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
var result worker.KojiFinalizeJobResult
|
|
Packit Service |
509fd4 |
err = impl.kojiImport(args.Server, build, buildRoots, images, args.KojiDirectory, initArgs.Token)
|
|
Packit Service |
509fd4 |
if err != nil {
|
|
Packit Service |
509fd4 |
result.KojiError = err.Error()
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
err = job.Update(&result)
|
|
Packit Service |
509fd4 |
if err != nil {
|
|
Packit Service |
509fd4 |
return fmt.Errorf("Error reporting job result: %v", err)
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
return nil
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
// Extracts dynamic args of the koji-finalize job. Returns an error if they
|
|
Packit Service |
509fd4 |
// cannot be unmarshalled.
|
|
Packit Service |
509fd4 |
func extractDynamicArgs(job worker.Job) (*worker.KojiInitJobResult, []worker.OSBuildKojiJobResult, error) {
|
|
Packit Service |
509fd4 |
var kojiInitResult worker.KojiInitJobResult
|
|
Packit Service |
509fd4 |
err := job.DynamicArgs(0, &kojiInitResult)
|
|
Packit Service |
509fd4 |
if err != nil {
|
|
Packit Service |
509fd4 |
return nil, nil, err
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
osbuildKojiResults := make([]worker.OSBuildKojiJobResult, job.NDynamicArgs()-1)
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
for i := 1; i < job.NDynamicArgs(); i++ {
|
|
Packit Service |
509fd4 |
err = job.DynamicArgs(i, &osbuildKojiResults[i-1])
|
|
Packit Service |
509fd4 |
if err != nil {
|
|
Packit Service |
509fd4 |
return nil, nil, err
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
return &kojiInitResult, osbuildKojiResults, nil
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
// Returns true if any of koji-finalize dependencies failed.
|
|
Packit Service |
509fd4 |
func hasFailedDependency(kojiInitResult worker.KojiInitJobResult, osbuildKojiResults []worker.OSBuildKojiJobResult) bool {
|
|
Packit Service |
509fd4 |
if kojiInitResult.KojiError != "" {
|
|
Packit Service |
509fd4 |
return true
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
|
|
Packit Service |
509fd4 |
for _, r := range osbuildKojiResults {
|
|
Packit Service |
509fd4 |
if !r.OSBuildOutput.Success || r.KojiError != "" {
|
|
Packit Service |
509fd4 |
return true
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
}
|
|
Packit Service |
509fd4 |
return false
|
|
Packit Service |
509fd4 |
}
|