Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 28 additions & 6 deletions matcher/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import (
. "github.com/onsi/gomega" //nolint:revive
)

// LogDir is where gathered logs are written. Relative paths resolve against the
// process working directory. The default preserves the historical behavior.
var LogDir = "logs"

type VM struct {
machine types.Machine
cancelFunc context.CancelFunc // We call it when we `Destroy` the VM
Expand Down Expand Up @@ -167,12 +171,13 @@ func machineGatherLog(m types.Machine, logPath string) {
}

baseName := filepath.Base(logPath)
_ = os.Mkdir("logs", 0755)
f, destination, err := createGatheredLogFile(LogDir, logPath)
if err != nil {
fmt.Printf("Couldn't create local log file for %s: %s\n", logPath, err)
return
}

f, _ := os.Create(fmt.Sprintf("logs/%s", baseName))
// Close the file after it has been copied
// Close client connection after the file has been copied
defer scpClient.Close()
// Close the file after it has been copied.
defer f.Close()

ctx, can := context.WithTimeout(context.Background(), 2*time.Minute)
Expand All @@ -183,10 +188,27 @@ func machineGatherLog(m types.Machine, logPath string) {
return
}
// Change perms so its world readable
_ = os.Chmod(fmt.Sprintf("logs/%s", baseName), 0666)
if err := os.Chmod(destination, 0o666); err != nil {
fmt.Printf("Couldn't change permissions on %s: %s\n", destination, err)
return
}
fmt.Printf("File %s copied!\n", baseName)
}

func createGatheredLogFile(logDir, logPath string) (*os.File, string, error) {
if err := os.MkdirAll(logDir, 0o755); err != nil {
return nil, "", fmt.Errorf("creating log directory %q: %w", logDir, err)
}

destination := filepath.Join(logDir, filepath.Base(logPath))
f, err := os.Create(destination)
if err != nil {
return nil, "", fmt.Errorf("creating gathered log %q: %w", destination, err)
}

return f, destination, nil
}

func machineHasFile(m types.Machine, s string) {
out, err := m.Command("if [ -f " + s + " ]; then echo ok; else echo wrong; fi")
Expect(err).ToNot(HaveOccurred())
Expand Down
103 changes: 103 additions & 0 deletions matcher/helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package matcher

import (
"os"
"path/filepath"
"testing"
)

func TestLogDirDefault(t *testing.T) {
if LogDir != "logs" {
t.Fatalf("LogDir default = %q, want %q", LogDir, "logs")
}
}

func TestCreateGatheredLogFileDefaultDir(t *testing.T) {
oldWorkingDir, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
if err := os.Chdir(t.TempDir()); err != nil {
t.Fatal(err)
}
t.Cleanup(func() { _ = os.Chdir(oldWorkingDir) })

f, destination, err := createGatheredLogFile(LogDir, "/var/log/messages")
if err != nil {
t.Fatal(err)
}
if err := f.Close(); err != nil {
t.Fatal(err)
}

want := filepath.Join("logs", "messages")
if destination != want {
t.Fatalf("destination = %q, want %q", destination, want)
}
if _, err := os.Stat(want); err != nil {
t.Fatalf("stat gathered log: %v", err)
}
}

func TestCreateGatheredLogFileAbsoluteNestedDir(t *testing.T) {
logDir := filepath.Join(t.TempDir(), "run", "gathered-logs")
f, destination, err := createGatheredLogFile(logDir, "/var/log/kern.log")
if err != nil {
t.Fatal(err)
}
if err := f.Close(); err != nil {
t.Fatal(err)
}

want := filepath.Join(logDir, "kern.log")
if destination != want {
t.Fatalf("destination = %q, want %q", destination, want)
}
if _, err := os.Stat(want); err != nil {
t.Fatalf("stat gathered log: %v", err)
}
}

func TestCreateGatheredLogFilePreservesBaseName(t *testing.T) {
logDir := t.TempDir()
f, destination, err := createGatheredLogFile(logDir, "/nested/remote/audit.json")
if err != nil {
t.Fatal(err)
}
if err := f.Close(); err != nil {
t.Fatal(err)
}

if got, want := filepath.Base(destination), "audit.json"; got != want {
t.Fatalf("destination base = %q, want %q", got, want)
}
}

func TestCreateGatheredLogFileInvalidDir(t *testing.T) {
parent := t.TempDir()
notDirectory := filepath.Join(parent, "not-a-directory")
if err := os.WriteFile(notDirectory, []byte("file"), 0o600); err != nil {
t.Fatal(err)
}

f, destination, err := createGatheredLogFile(filepath.Join(notDirectory, "logs"), "/var/log/messages")
if err == nil {
t.Fatal("expected an error")
}
if f != nil {
t.Fatal("expected no file on error")
}
if destination != "" {
t.Fatalf("destination = %q, want empty", destination)
}
}

func TestCreateGatheredLogFileInvalidDestination(t *testing.T) {
f, destination, err := createGatheredLogFile(t.TempDir(), ".")
if err == nil {
t.Fatal("expected an error")
}
if f != nil || destination != "" {
t.Fatalf("result = %#v, %q; want nil, empty", f, destination)
}
}