github.com/askholme/packer@v0.7.2-0.20140924152349-70d9566a6852/post-processor/compress/post-processor.go (about) 1 package compress 2 3 import ( 4 "archive/tar" 5 "compress/gzip" 6 "fmt" 7 "io" 8 "os" 9 10 "github.com/mitchellh/packer/common" 11 "github.com/mitchellh/packer/packer" 12 ) 13 14 type Config struct { 15 common.PackerConfig `mapstructure:",squash"` 16 17 OutputPath string `mapstructure:"output"` 18 19 tpl *packer.ConfigTemplate 20 } 21 22 type PostProcessor struct { 23 config Config 24 } 25 26 func (self *PostProcessor) Configure(raws ...interface{}) error { 27 _, err := common.DecodeConfig(&self.config, raws...) 28 if err != nil { 29 return err 30 } 31 32 self.config.tpl, err = packer.NewConfigTemplate() 33 if err != nil { 34 return err 35 } 36 self.config.tpl.UserVars = self.config.PackerUserVars 37 38 templates := map[string]*string{ 39 "output": &self.config.OutputPath, 40 } 41 42 errs := new(packer.MultiError) 43 for key, ptr := range templates { 44 if *ptr == "" { 45 errs = packer.MultiErrorAppend( 46 errs, fmt.Errorf("%s must be set", key)) 47 } 48 49 *ptr, err = self.config.tpl.Process(*ptr, nil) 50 if err != nil { 51 errs = packer.MultiErrorAppend( 52 errs, fmt.Errorf("Error processing %s: %s", key, err)) 53 } 54 } 55 56 if len(errs.Errors) > 0 { 57 return errs 58 } 59 60 return nil 61 62 } 63 64 func (self *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) { 65 ui.Say(fmt.Sprintf("Creating archive for '%s'", artifact.BuilderId())) 66 67 // Create the compressed archive file at the appropriate OutputPath. 68 fw, err := os.Create(self.config.OutputPath) 69 if err != nil { 70 return nil, false, fmt.Errorf( 71 "Failed creating file for compressed archive: %s", self.config.OutputPath) 72 } 73 defer fw.Close() 74 75 gw := gzip.NewWriter(fw) 76 defer gw.Close() 77 78 // Iterate through all of the artifact's files and put them into the 79 // compressed archive using the tar/gzip writers. 80 for _, path := range artifact.Files() { 81 fi, err := os.Stat(path) 82 if err != nil { 83 return nil, false, fmt.Errorf( 84 "Failed stating file: %s", path) 85 } 86 87 target, _ := os.Readlink(path) 88 header, err := tar.FileInfoHeader(fi, target) 89 if err != nil { 90 return nil, false, fmt.Errorf( 91 "Failed creating archive header: %s", path) 92 } 93 94 tw := tar.NewWriter(gw) 95 defer tw.Close() 96 97 // Write the header first to the archive. This takes partial data 98 // from the FileInfo that is grabbed by running the stat command. 99 if err := tw.WriteHeader(header); err != nil { 100 return nil, false, fmt.Errorf( 101 "Failed writing archive header: %s", path) 102 } 103 104 // Open the target file for archiving and compressing. 105 fr, err := os.Open(path) 106 if err != nil { 107 return nil, false, fmt.Errorf( 108 "Failed opening file '%s' to write compressed archive.", path) 109 } 110 defer fr.Close() 111 112 if _, err = io.Copy(tw, fr); err != nil { 113 return nil, false, fmt.Errorf( 114 "Failed copying file to archive: %s", path) 115 } 116 } 117 118 return NewArtifact(artifact.BuilderId(), self.config.OutputPath), false, nil 119 }