github.com/darmach/terratest@v0.34.8-0.20210517103231-80931f95e3ff/modules/logger/parser/store.go (about)

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