mirror of https://github.com/containers/conmon.git
191 lines
4.2 KiB
Go
191 lines
4.2 KiB
Go
package conmon_test
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"os/exec"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/containers/conmon/runner/conmon"
|
|
"github.com/coreos/go-systemd/v22/sdjournal"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var (
|
|
conmonPath = "/usr/bin/conmon"
|
|
runtimePath = "/usr/bin/runc"
|
|
busyboxSource = "https://busybox.net/downloads/binaries/1.31.0-i686-uclibc/busybox"
|
|
busyboxDestDir = "/tmp/conmon-test-images"
|
|
busyboxDest = "/tmp/conmon-test-images/busybox"
|
|
ctrID = "abcdefghijklm"
|
|
validPath = "/tmp"
|
|
invalidPath = "/not/a/path"
|
|
)
|
|
|
|
func TestConmon(t *testing.T) {
|
|
configureSuiteFromEnv()
|
|
RegisterFailHandler(Fail)
|
|
RunSpecs(t, "Conmon Suite")
|
|
}
|
|
|
|
func getConmonOutputGivenOptions(options ...conmon.ConmonOption) (string, string) {
|
|
var stdout bytes.Buffer
|
|
var stderr bytes.Buffer
|
|
var stdin bytes.Buffer
|
|
|
|
options = append(options, conmon.WithStdout(&stdout), conmon.WithStderr(&stderr), conmon.WithStdin(&stdin))
|
|
|
|
ci, err := conmon.CreateAndExecConmon(options...)
|
|
Expect(err).To(BeNil())
|
|
|
|
defer ci.Cleanup()
|
|
|
|
ci.Wait()
|
|
|
|
pid, _ := ci.Pid()
|
|
if pid < 0 {
|
|
return stdout.String(), stderr.String()
|
|
}
|
|
|
|
_, err = ci.ContainerExitCode()
|
|
Expect(err).To(BeNil())
|
|
|
|
journalerr, err := getConmonJournalOutput(pid, 3)
|
|
Expect(err).To(BeNil())
|
|
|
|
alljournalout, err := getConmonJournalOutput(pid, -1)
|
|
Expect(err).To(BeNil())
|
|
fmt.Fprintln(GinkgoWriter, alljournalout)
|
|
|
|
return stdout.String(), stderr.String() + journalerr
|
|
}
|
|
|
|
func getConmonJournalOutput(pid int, level int) (string, error) {
|
|
matches := []sdjournal.Match{
|
|
{
|
|
Field: sdjournal.SD_JOURNAL_FIELD_COMM,
|
|
Value: "conmon",
|
|
},
|
|
{
|
|
Field: sdjournal.SD_JOURNAL_FIELD_PID,
|
|
Value: strconv.Itoa(pid),
|
|
},
|
|
}
|
|
if level > 0 {
|
|
matches = append(matches, sdjournal.Match{
|
|
Field: sdjournal.SD_JOURNAL_FIELD_PRIORITY,
|
|
Value: strconv.Itoa(level),
|
|
})
|
|
}
|
|
r, err := sdjournal.NewJournalReader(sdjournal.JournalReaderConfig{
|
|
Matches: matches,
|
|
Formatter: formatter,
|
|
})
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer r.Close()
|
|
|
|
return readAllFromBuffer(r)
|
|
}
|
|
|
|
func formatter(entry *sdjournal.JournalEntry) (string, error) {
|
|
return entry.Fields[sdjournal.SD_JOURNAL_FIELD_MESSAGE], nil
|
|
}
|
|
|
|
func readAllFromBuffer(r io.ReadCloser) (string, error) {
|
|
bufLen := 16384
|
|
stringOutput := ""
|
|
|
|
bytes := make([]byte, bufLen)
|
|
// /me complains about no do-while in go
|
|
ec, err := r.Read(bytes)
|
|
for ec != 0 && err == nil {
|
|
// because we are reusing bytes, we need to make
|
|
// sure the old data doesn't get into the new line
|
|
bytestr := string(bytes[:ec])
|
|
stringOutput += string(bytestr)
|
|
ec, err = r.Read(bytes)
|
|
}
|
|
if err != nil && err != io.EOF {
|
|
return stringOutput, err
|
|
}
|
|
return stringOutput, nil
|
|
}
|
|
|
|
func configureSuiteFromEnv() {
|
|
if path := os.Getenv("CONMON_BINARY"); path != "" {
|
|
conmonPath = path
|
|
}
|
|
if path := os.Getenv("RUNTIME_BINARY"); path != "" {
|
|
runtimePath = path
|
|
}
|
|
}
|
|
|
|
func cacheBusyBox() error {
|
|
if _, err := os.Stat(busyboxDest); err == nil {
|
|
return nil
|
|
}
|
|
if err := os.MkdirAll(busyboxDestDir, 0o755); err != nil && !os.IsExist(err) {
|
|
return err
|
|
}
|
|
if err := downloadFile(busyboxSource, busyboxDest); err != nil {
|
|
return err
|
|
}
|
|
if err := os.Chmod(busyboxDest, 0o777); err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// source: https://progolang.com/how-to-download-files-in-go/
|
|
// downloadFile will download a url and store it in local filepath.
|
|
// It writes to the destination file as it downloads it, without
|
|
// loading the entire file into memory.
|
|
func downloadFile(url string, filepath string) error {
|
|
// Create the file
|
|
out, err := os.Create(filepath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer out.Close()
|
|
|
|
// Get the data
|
|
resp, err := http.Get(url)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
// Write the body to file
|
|
_, err = io.Copy(out, resp.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func runRuntimeCommand(args ...string) error {
|
|
var stdout bytes.Buffer
|
|
var stderr bytes.Buffer
|
|
|
|
cmd := exec.Command(runtimePath, args...)
|
|
cmd.Stdout = &stdout
|
|
cmd.Stderr = &stderr
|
|
if err := cmd.Run(); err != nil {
|
|
return err
|
|
}
|
|
cmd.Run()
|
|
stdoutString := stdout.String()
|
|
if stdoutString != "" {
|
|
fmt.Fprintln(GinkgoWriter, stdoutString)
|
|
}
|
|
return nil
|
|
}
|