debian-forge-composer/cmd/osbuild-koji-tests/main_test.go
Brian C. Lane 7a4bb863dd Update deprecated io/ioutil functions
ioutil has been deprecated since go 1.16, this fixes all of the
deprecated functions we are using:

ioutil.ReadFile -> os.ReadFile
ioutil.ReadAll -> io.ReadAll
ioutil.WriteFile -> os.WriteFile
ioutil.TempFile -> os.CreateTemp
ioutil.TempDir -> os.MkdirTemp

All of the above are a simple name change, the function arguments and
results are exactly the same as before.

ioutil.ReadDir -> os.ReadDir

now returns a os.DirEntry but the IsDir and Name functions work the
same. The difference is that the FileInfo must be retrieved with the
Info() function which can also return an error.

These were identified by running:
golangci-lint run --build-tags=integration ./...
2023-03-07 09:22:23 -08:00

220 lines
5.6 KiB
Go

// 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.
//go:build integration
// +build integration
package main
import (
"crypto/rand"
"crypto/tls"
"crypto/x509"
"io"
"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/rpmmd"
"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 := os.ReadFile(shareDir + "/ca-crt.pem")
require.NoError(t, err)
ok := certPool.AppendCertsFromPEM(cert)
require.True(t, ok)
transport.TLSClientConfig = &tls.Config{
RootCAs: certPool,
MinVersion: tls.VersionTLS12,
}
// 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 := os.ReadFile(shareDir + "/ca-crt.pem")
require.NoError(t, err)
ok := certPool.AppendCertsFromPEM(cert)
require.True(t, ok)
transport.TLSClientConfig = &tls.Config{
RootCAs: certPool,
MinVersion: tls.VersionTLS12,
}
// 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 := os.CreateTemp("", "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: []rpmmd.RPM{},
},
}
output := []koji.Image{
{
BuildRootID: 1,
Filename: filename,
FileSize: uint64(filesize),
Arch: "noarch",
ChecksumType: "md5",
MD5: hash,
Type: "image",
RPMs: []rpmmd.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:
// There's no potential command injection vector here
/* #nosec G204 */
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")
}