forked from gruntwork-io/terratest
-
Notifications
You must be signed in to change notification settings - Fork 0
/
store.go
111 lines (100 loc) · 3.58 KB
/
store.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Package logger/parser contains methods to parse and restructure log output from go testing and terratest
package parser
import (
"os"
"path/filepath"
"github.com/gruntwork-io/go-commons/errors"
"github.com/gruntwork-io/go-commons/files"
junitformatter "github.com/jstemmer/go-junit-report/formatter"
junitparser "github.com/jstemmer/go-junit-report/parser"
"github.com/sirupsen/logrus"
)
type LogWriter struct {
// Represents an open file to a log corresponding to a test (key = test name)
lookup map[string]*os.File
outputDir string
}
// LogWriter.getOrCreateFile will get the corresponding file to a log for the provided test name, or create a new file.
func (logWriter LogWriter) getOrCreateFile(logger *logrus.Logger, testName string) (*os.File, error) {
file, hasKey := logWriter.lookup[testName]
if hasKey {
return file, nil
}
filename := filepath.Join(logWriter.outputDir, testName+".log")
file, err := createLogFile(logger, filename)
if err != nil {
return nil, errors.WithStackTrace(err)
}
logWriter.lookup[testName] = file
return file, nil
}
// LogWriter.closeChannels closes all the channels in the lookup dictionary
func (logWriter LogWriter) closeFiles(logger *logrus.Logger) {
logger.Infof("Closing all the files in log writer")
for testName, file := range logWriter.lookup {
err := file.Close()
if err != nil {
logger.Errorf("Error closing log file for test %s: %s", testName, err)
}
}
}
// writeLog will write the provided text to the corresponding log file for the provided test.
func (logWriter LogWriter) writeLog(logger *logrus.Logger, testName string, text string) error {
file, err := logWriter.getOrCreateFile(logger, testName)
if err != nil {
logger.Errorf("Error retrieving log for test: %s", testName)
return errors.WithStackTrace(err)
}
_, err = file.WriteString(text + "\n")
if err != nil {
logger.Errorf("Error (%s) writing log entry: %s", err, text)
return errors.WithStackTrace(err)
}
file.Sync()
return nil
}
// createLogFile will create and return the open file handle for the file at provided filename, creating all directories
// in the process.
func createLogFile(logger *logrus.Logger, filename string) (*os.File, error) {
// We extract and create the directory for interpolated filename, to handle nested tests where testname contains '/'
dirName := filepath.Dir(filename)
err := ensureDirectoryExists(logger, dirName)
if err != nil {
return nil, errors.WithStackTrace(err)
}
file, err := os.Create(filename)
if err != nil {
return nil, errors.WithStackTrace(err)
}
return file, nil
}
// ensureDirectoryExists will only attempt to create the directory if it does not exist
func ensureDirectoryExists(logger *logrus.Logger, dirName string) error {
if files.IsDir(dirName) {
logger.Infof("Directory %s already exists", dirName)
return nil
}
logger.Infof("Creating directory %s", dirName)
err := os.MkdirAll(dirName, os.ModePerm)
if err != nil {
logger.Errorf("Error making directory %s: %s", dirName, err)
return errors.WithStackTrace(err)
}
return nil
}
// storeJunitReport takes a parsed Junit report and stores it as report.xml in the output directory
func storeJunitReport(logger *logrus.Logger, outputDir string, report *junitparser.Report) {
ensureDirectoryExists(logger, outputDir)
filename := filepath.Join(outputDir, "report.xml")
f, err := os.Create(filename)
if err != nil {
logger.Errorf("Error making file %s for junit report", filename)
return
}
defer f.Close()
err = junitformatter.JUnitReportXML(report, false, "", f)
if err != nil {
logger.Errorf("Error formatting junit xml report: %s", err)
return
}
}