Merge pull request #15 from OpenCHAMI/compress

Add option to compress/archive multiple generated files
This commit is contained in:
David Allen 2024-10-02 11:04:09 -06:00 committed by GitHub
commit 9f0e48eb7f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 84 additions and 0 deletions

View file

@ -21,6 +21,7 @@ var (
templatePaths []string templatePaths []string
pluginPath string pluginPath string
cacertPath string cacertPath string
useCompression bool
) )
var generateCmd = &cobra.Command{ var generateCmd = &cobra.Command{
@ -121,6 +122,25 @@ func RunTargets(config *configurator.Config, args []string, targets ...string) {
} }
log.Info().Msgf("wrote file to '%s'\n", outputPath) log.Info().Msgf("wrote file to '%s'\n", outputPath)
} }
} else if outputPath != "" && targetCount > 1 && useCompression {
// write multiple files to archive, compress, then save to output path
out, err := os.Create(fmt.Sprintf("%s.tar.gz", outputPath))
if err != nil {
log.Error().Err(err).Msg("failed to write archive")
os.Exit(1)
}
files := make([]string, len(outputBytes))
i := 0
for path := range outputBytes {
files[i] = path
i++
}
err = util.CreateArchive(files, out)
if err != nil {
log.Error().Err(err).Msg("failed to create archive")
os.Exit(1)
}
} else if outputPath != "" && targetCount > 1 || templateCount > 1 { } else if outputPath != "" && targetCount > 1 || templateCount > 1 {
// write multiple files in directory using template name // write multiple files in directory using template name
err := os.MkdirAll(filepath.Clean(outputPath), 0o755) err := os.MkdirAll(filepath.Clean(outputPath), 0o755)
@ -159,6 +179,7 @@ func init() {
generateCmd.Flags().IntVar(&tokenFetchRetries, "fetch-retries", 5, "set the number of retries to fetch an access token") generateCmd.Flags().IntVar(&tokenFetchRetries, "fetch-retries", 5, "set the number of retries to fetch an access token")
generateCmd.Flags().StringVar(&remoteHost, "host", "http://localhost", "set the remote host") generateCmd.Flags().StringVar(&remoteHost, "host", "http://localhost", "set the remote host")
generateCmd.Flags().IntVar(&remotePort, "port", 80, "set the remote port") generateCmd.Flags().IntVar(&remotePort, "port", 80, "set the remote port")
generateCmd.Flags().BoolVar(&useCompression, "compress", false, "set whether to archive and compress multiple file outputs")
// requires either 'target' by itself or 'plugin' and 'templates' together // requires either 'target' by itself or 'plugin' and 'templates' together
// generateCmd.MarkFlagsOneRequired("target", "plugin") // generateCmd.MarkFlagsOneRequired("target", "plugin")

View file

@ -1,8 +1,10 @@
package util package util
import ( import (
"archive/tar"
"bytes" "bytes"
"cmp" "cmp"
"compress/gzip"
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"io" "io"
@ -97,3 +99,64 @@ func CopyIf[T comparable](s []T, condition func(t T) bool) []T {
} }
return f return f
} }
func CreateArchive(files []string, buf io.Writer) error {
// Create new Writers for gzip and tar
// These writers are chained. Writing to the tar writer will
// write to the gzip writer which in turn will write to
// the "buf" writer
gw := gzip.NewWriter(buf)
defer gw.Close()
tw := tar.NewWriter(gw)
defer tw.Close()
// Iterate over files and add them to the tar archive
for _, file := range files {
err := addToArchive(tw, file)
if err != nil {
return err
}
}
return nil
}
func addToArchive(tw *tar.Writer, filename string) error {
// open file to write to archive
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
// get FileInfo for file size, mode, etc.
info, err := file.Stat()
if err != nil {
return err
}
// create a tar Header from the FileInfo data
header, err := tar.FileInfoHeader(info, info.Name())
if err != nil {
return err
}
// use full path as name (FileInfoHeader only takes the basename) to
// preserve directory structure
// see for more info: https://golang.org/src/archive/tar/common.go?#L626
header.Name = filename
// Write file header to the tar archive
err = tw.WriteHeader(header)
if err != nil {
return err
}
// copy file content to tar archive
_, err = io.Copy(tw, file)
if err != nil {
return err
}
return nil
}