diff --git a/diagnostic/diagnostic_utils.go b/diagnostic/diagnostic_utils.go new file mode 100644 index 00000000..a14f2efa --- /dev/null +++ b/diagnostic/diagnostic_utils.go @@ -0,0 +1,69 @@ +package diagnostic + +import ( + "archive/zip" + "fmt" + "io" + "os" + "path/filepath" + "strings" + "time" +) + +// CreateDiagnosticZipFile create a zip file with the contents from the all +// files paths. The files will be written in the root of the zip file. +// In case of an error occurs after whilst writing to the zip file +// this will be removed. +func CreateDiagnosticZipFile(base string, paths []string) (zipFileName string, err error) { + // Create a zip file with all files from paths added to the root + suffix := time.Now().Format(time.RFC3339) + zipFileName = base + "-" + suffix + ".zip" + zipFileName = strings.ReplaceAll(zipFileName, ":", "-") + + archive, cerr := os.Create(zipFileName) + if cerr != nil { + return "", fmt.Errorf("error creating file %s: %w", zipFileName, cerr) + } + + archiveWriter := zip.NewWriter(archive) + + defer func() { + archiveWriter.Close() + archive.Close() + + if err != nil { + os.Remove(zipFileName) + } + }() + + for _, file := range paths { + if file == "" { + continue + } + + var handle *os.File + + handle, err = os.Open(file) + if err != nil { + return "", fmt.Errorf("error opening file %s: %w", zipFileName, err) + } + + defer handle.Close() + + // Keep the base only to not create sub directories in the + // zip file. + var writer io.Writer + + writer, err = archiveWriter.Create(filepath.Base(file)) + if err != nil { + return "", fmt.Errorf("error creating archive writer from %s: %w", file, err) + } + + if _, err = io.Copy(writer, handle); err != nil { + return "", fmt.Errorf("error copying file %s: %w", file, err) + } + } + + zipFileName = archive.Name() + return zipFileName, nil +}