github.com/Foodji/aws-lambda-go@v1.20.2/cmd/build-lambda-zip/main.go (about) 1 // Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved 2 3 package main 4 5 import ( 6 "archive/zip" 7 "errors" 8 "fmt" 9 "io/ioutil" 10 "log" 11 "os" 12 "path/filepath" 13 14 "github.com/urfave/cli/v2" 15 ) 16 17 func main() { 18 app := &cli.App{ 19 Name: "build-lambda-zip", 20 Usage: "Put an executable and supplemental files into a zip file that works with AWS Lambda.", 21 Flags: []cli.Flag{ 22 &cli.StringFlag{ 23 Name: "output", 24 Aliases: []string{"o"}, 25 Value: "", 26 Usage: "output file path for the zip. Defaults to the first input file name.", 27 }, 28 }, 29 Action: func(c *cli.Context) error { 30 if !c.Args().Present() { 31 return errors.New("no input provided") 32 } 33 34 inputExe := c.Args().First() 35 outputZip := c.String("output") 36 if outputZip == "" { 37 outputZip = fmt.Sprintf("%s.zip", filepath.Base(inputExe)) 38 } 39 40 if err := compressExeAndArgs(outputZip, inputExe, c.Args().Tail()); err != nil { 41 return fmt.Errorf("failed to compress file: %v", err) 42 } 43 log.Print("wrote " + outputZip) 44 return nil 45 }, 46 } 47 48 if err := app.Run(os.Args); err != nil { 49 fmt.Fprintf(os.Stderr, "%v\n", err) 50 os.Exit(1) 51 } 52 } 53 54 func writeExe(writer *zip.Writer, pathInZip string, data []byte) error { 55 if pathInZip != "bootstrap" { 56 header := &zip.FileHeader{Name: "bootstrap", Method: zip.Deflate} 57 header.SetMode(0755 | os.ModeSymlink) 58 link, err := writer.CreateHeader(header) 59 if err != nil { 60 return err 61 } 62 if _, err := link.Write([]byte(pathInZip)); err != nil { 63 return err 64 } 65 } 66 67 exe, err := writer.CreateHeader(&zip.FileHeader{ 68 CreatorVersion: 3 << 8, // indicates Unix 69 ExternalAttrs: 0777 << 16, // -rwxrwxrwx file permissions 70 Name: pathInZip, 71 Method: zip.Deflate, 72 }) 73 if err != nil { 74 return err 75 } 76 77 _, err = exe.Write(data) 78 return err 79 } 80 81 func compressExeAndArgs(outZipPath string, exePath string, args []string) error { 82 zipFile, err := os.Create(outZipPath) 83 if err != nil { 84 return err 85 } 86 defer func() { 87 closeErr := zipFile.Close() 88 if closeErr != nil { 89 fmt.Fprintf(os.Stderr, "Failed to close zip file: %v\n", closeErr) 90 } 91 }() 92 93 zipWriter := zip.NewWriter(zipFile) 94 defer zipWriter.Close() 95 data, err := ioutil.ReadFile(exePath) 96 if err != nil { 97 return err 98 } 99 100 err = writeExe(zipWriter, filepath.Base(exePath), data) 101 if err != nil { 102 return err 103 } 104 105 for _, arg := range args { 106 writer, err := zipWriter.Create(arg) 107 if err != nil { 108 return err 109 } 110 data, err := ioutil.ReadFile(arg) 111 if err != nil { 112 return err 113 } 114 _, err = writer.Write(data) 115 if err != nil { 116 return err 117 } 118 } 119 return err 120 }