github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/plugin/builtin/archive/tar_gz_pack_command.go (about) 1 package archive 2 3 import ( 4 "os" 5 "path/filepath" 6 7 "github.com/evergreen-ci/evergreen/archive" 8 "github.com/evergreen-ci/evergreen/model" 9 "github.com/evergreen-ci/evergreen/plugin" 10 "github.com/mitchellh/mapstructure" 11 "github.com/mongodb/grip" 12 "github.com/mongodb/grip/send" 13 "github.com/mongodb/grip/slogger" 14 "github.com/pkg/errors" 15 ) 16 17 // Plugin command responsible for creating a tgz archive. 18 type TarGzPackCommand struct { 19 // the tgz file that will be created 20 Target string `mapstructure:"target" plugin:"expand"` 21 22 // the directory to compress 23 SourceDir string `mapstructure:"source_dir" plugin:"expand"` 24 25 // a list of filename blobs to include, 26 // e.g. "*.tgz", "file.txt", "test_*" 27 Include []string `mapstructure:"include" plugin:"expand"` 28 29 // a list of filename blobs to exclude, 30 // e.g. "*.zip", "results.out", "ignore/**" 31 ExcludeFiles []string `mapstructure:"exclude_files" plugin:"expand"` 32 } 33 34 func (self *TarGzPackCommand) Name() string { 35 return TarGzPackCmdName 36 } 37 38 func (self *TarGzPackCommand) Plugin() string { 39 return ArchivePluginName 40 } 41 42 // ParseParams reads in the given parameters for the command. 43 func (self *TarGzPackCommand) ParseParams(params map[string]interface{}) error { 44 if err := mapstructure.Decode(params, self); err != nil { 45 return errors.Wrapf(err, "error parsing '%v' params", self.Name()) 46 } 47 if err := self.validateParams(); err != nil { 48 return errors.Wrapf(err, "error validating '%v' params", self.Name()) 49 } 50 return nil 51 } 52 53 // Make sure a target and source dir are set, and files are specified to be 54 // included. 55 func (self *TarGzPackCommand) validateParams() error { 56 if self.Target == "" { 57 return errors.New("target cannot be blank") 58 } 59 if self.SourceDir == "" { 60 return errors.New("source_dir cannot be blank") 61 } 62 if len(self.Include) == 0 { 63 return errors.New("include cannot be empty") 64 } 65 66 return nil 67 } 68 69 // Execute builds the archive. 70 func (self *TarGzPackCommand) Execute(pluginLogger plugin.Logger, 71 pluginCom plugin.PluginCommunicator, 72 conf *model.TaskConfig, 73 stop chan bool) error { 74 75 if err := plugin.ExpandValues(self, conf.Expansions); err != nil { 76 return errors.Wrap(err, "error expanding params") 77 } 78 79 // if the source dir is a relative path, join it to the working dir 80 if !filepath.IsAbs(self.SourceDir) { 81 self.SourceDir = filepath.Join(conf.WorkDir, self.SourceDir) 82 } 83 84 // if the target is a relative path, join it to the working dir 85 if !filepath.IsAbs(self.Target) { 86 self.Target = filepath.Join(conf.WorkDir, self.Target) 87 } 88 89 errChan := make(chan error) 90 filesArchived := -1 91 go func() { 92 var err error 93 filesArchived, err = self.BuildArchive(pluginLogger) 94 errChan <- errors.WithStack(err) 95 }() 96 97 select { 98 case err := <-errChan: 99 if err != nil { 100 return errors.WithStack(err) 101 } 102 if filesArchived == 0 { 103 deleteErr := os.Remove(self.Target) 104 if deleteErr != nil { 105 pluginLogger.LogExecution(slogger.INFO, "Error deleting empty archive: %v", deleteErr) 106 } 107 } 108 return nil 109 case <-stop: 110 pluginLogger.LogExecution(slogger.INFO, "Received signal to terminate"+ 111 " execution of targz pack command") 112 return nil 113 } 114 115 } 116 117 // since archive.BuildArchive takes in a slogger.Logger 118 type agentAppender struct { 119 pluginLogger plugin.Logger 120 } 121 122 // satisfy the slogger.Appender interface 123 func (self *agentAppender) Append(log *slogger.Log) error { 124 self.pluginLogger.LogExecution(log.Level, slogger.FormatLog(log)) 125 return nil 126 } 127 128 // Build the archive. 129 // Returns the number of files included in the archive (0 means empty archive). 130 func (self *TarGzPackCommand) BuildArchive(pluginLogger plugin.Logger) (int, error) { 131 // create a logger to pass into the BuildArchive command 132 appender := &agentAppender{ 133 pluginLogger: pluginLogger, 134 } 135 136 log := &slogger.Logger{ 137 Name: "", 138 Appenders: []send.Sender{slogger.WrapAppender(appender)}, 139 } 140 141 // create a targz writer for the target file 142 f, gz, tarWriter, err := archive.TarGzWriter(self.Target) 143 if err != nil { 144 return -1, errors.Wrapf(err, "error opening target archive file %s", self.Target) 145 } 146 defer func() { 147 grip.CatchError(tarWriter.Close()) 148 grip.CatchError(gz.Close()) 149 grip.CatchError(f.Close()) 150 }() 151 152 // Build the archive 153 out, err := archive.BuildArchive(tarWriter, self.SourceDir, self.Include, 154 self.ExcludeFiles, log) 155 return out, errors.WithStack(err) 156 }