// This command contains some tests for the koji integration. It's a bit // different from the other cmd/*-tests executables because it cannot be // currently run as a "base test". Instead, it's run as a part of the // koji.sh test because it needs a working Koji instance to pass. // +build integration package main import ( "crypto/rand" "crypto/tls" "crypto/x509" "io" "io/ioutil" "net/http" "os" "os/exec" "strconv" "testing" "time" "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/osbuild/osbuild-composer/internal/upload/koji" ) func TestKojiRefund(t *testing.T) { shareDir := "/tmp/osbuild-composer-koji-test" server := "https://localhost:4343/kojihub" // base our transport on the default one transport := http.DefaultTransport.(*http.Transport).Clone() // use the self-signed certificate generated by run-koji-container certPool := x509.NewCertPool() cert, err := ioutil.ReadFile(shareDir + "/ca-crt.pem") require.NoError(t, err) ok := certPool.AppendCertsFromPEM(cert) require.True(t, ok) transport.TLSClientConfig = &tls.Config{ RootCAs: certPool, } // login credentials := &koji.GSSAPICredentials{ Principal: "osbuild-krb@LOCAL", KeyTab: shareDir + "/client.keytab", } k, err := koji.NewFromGSSAPI(server, credentials, transport) require.NoError(t, err) defer func() { err := k.Logout() if err != nil { require.NoError(t, err) } }() initResult, err := k.CGInitBuild("name", "verison", "release") require.NoError(t, err) err = k.CGCancelBuild(initResult.BuildID, initResult.Token) require.NoError(t, err) err = k.CGCancelBuild(initResult.BuildID, initResult.Token) require.Error(t, err) initResult, err = k.CGInitBuild("name", "verison", "release") require.NoError(t, err) err = k.CGFailBuild(initResult.BuildID, initResult.Token) require.NoError(t, err) err = k.CGFailBuild(initResult.BuildID, initResult.Token) require.Error(t, err) } func TestKojiImport(t *testing.T) { // define constants server := "https://localhost:4343/kojihub" filename := "image.qcow2" filesize := 1024 shareDir := "/tmp/osbuild-composer-koji-test" // you cannot create two build with a same name, let's create a random one each time buildName := "osbuild-image-" + uuid.Must(uuid.NewRandom()).String() // koji needs to specify a directory to which the upload should happen, let's reuse the build name uploadDirectory := buildName // base our transport on the default one transport := http.DefaultTransport.(*http.Transport).Clone() // use the self-signed certificate generated by run-koji-container certPool := x509.NewCertPool() cert, err := ioutil.ReadFile(shareDir + "/ca-crt.pem") require.NoError(t, err) ok := certPool.AppendCertsFromPEM(cert) require.True(t, ok) transport.TLSClientConfig = &tls.Config{ RootCAs: certPool, } // login credentials := &koji.GSSAPICredentials{ Principal: "osbuild-krb@LOCAL", KeyTab: shareDir + "/client.keytab", } k, err := koji.NewFromGSSAPI(server, credentials, transport) require.NoError(t, err) defer func() { err := k.Logout() if err != nil { require.NoError(t, err) } }() // Create a random file f, err := ioutil.TempFile("", "osbuild-koji-test-*.qcow2") require.NoError(t, err) defer func() { assert.NoError(t, f.Close()) assert.NoError(t, os.Remove(f.Name())) }() _, err = io.CopyN(f, rand.Reader, int64(filesize)) require.NoError(t, err) _, err = f.Seek(0, io.SeekStart) require.NoError(t, err) // Upload the file hash, _, err := k.Upload(f, uploadDirectory, filename) require.NoError(t, err) // Import the build build := koji.ImageBuild{ TaskID: 1, Name: buildName, Version: "1", Release: "1", StartTime: time.Now().Unix(), EndTime: time.Now().Unix(), } buildRoots := []koji.BuildRoot{ { ID: 1, Host: koji.Host{ Os: "RHEL8", Arch: "noarch", }, ContentGenerator: koji.ContentGenerator{ Name: "osbuild", Version: "1", }, Container: koji.Container{ Type: "nspawn", Arch: "noarch", }, Tools: []koji.Tool{}, RPMs: []koji.RPM{}, }, } output := []koji.Image{ { BuildRootID: 1, Filename: filename, FileSize: uint64(filesize), Arch: "noarch", ChecksumType: "md5", MD5: hash, Type: "image", RPMs: []koji.RPM{}, Extra: koji.ImageExtra{ Info: koji.ImageExtraInfo{ Arch: "noarch", }, }, }, } initResult, err := k.CGInitBuild(build.Name, build.Version, build.Release) require.NoError(t, err) build.BuildID = uint64(initResult.BuildID) importResult, err := k.CGImport(build, buildRoots, output, uploadDirectory, initResult.Token) require.NoError(t, err) // check if the build is really there: cmd := exec.Command( "koji", "--server", server, "-c", "/usr/share/tests/osbuild-composer/koji/koji.conf", "--keytab", credentials.KeyTab, "--principal", credentials.Principal, "list-builds", "--buildid", strconv.Itoa(importResult.BuildID), ) // sample output: // Build Built by State // ------------------------------------------------------- ---------------- ---------------- // osbuild-image-92882b90-4bd9-4422-8b8a-40863f94535a-1-1 osbuild COMPLETE out, err := cmd.CombinedOutput() assert.NoError(t, err) // let's check for COMPLETE, koji will exit with non-zero status code if the build doesn't exist assert.Contains(t, string(out), "COMPLETE") }