Skip to content

Commit b28b12f

Browse files
committed
Upload go binaries as functions
With AWSLambda supporting Go, I thought it'd be interesting to do some exploration to support them. Go support requires binary files, so we cannot depend on the file extension to know if what we're uploading is JS or Go. Instead, we can have a well known path convention to put Go binaries, like `well-known-go`, and assume that all executables there are Go binaries. We'd also need a way to tell our API that something should use the go runtime and not the js runtime. I added a `Runtime` attribute to the file bundle, so we can configure aws lambda with the right flags. Signed-off-by: David Calavera <[email protected]>
1 parent ab8a201 commit b28b12f

File tree

1 file changed

+76
-35
lines changed

1 file changed

+76
-35
lines changed

go/porcelain/deploy.go

Lines changed: 76 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ type uploadError struct {
7676
}
7777

7878
type FileBundle struct {
79-
Name string
80-
Sum string
79+
Name string
80+
Sum string
81+
Runtime string
8182

8283
// Path OR Buffer should be populated
8384
Path string
@@ -501,55 +502,95 @@ func bundle(functionDir string, observer DeployObserver) (*deployFiles, error) {
501502
return nil, err
502503
}
503504
for _, i := range info {
504-
switch filepath.Ext(i.Name()) {
505-
case ".js":
506-
file := &FileBundle{
507-
Name: strings.TrimSuffix(i.Name(), filepath.Ext(i.Name())),
508-
}
509-
510-
s := sha256.New()
511-
buf := new(bytes.Buffer)
512-
archive := zip.NewWriter(buf)
513-
fileHeader, err := archive.Create(i.Name())
514-
if err != nil {
515-
return nil, err
516-
}
517-
fileEntry, err := os.Open(filepath.Join(functionDir, i.Name()))
505+
switch {
506+
case jsFile(i):
507+
file, err := newFunctionFile(functionDir, i, "js")
518508
if err != nil {
519509
return nil, err
520510
}
521-
defer fileEntry.Close()
522-
if _, err = io.Copy(fileHeader, fileEntry); err != nil {
523-
return nil, err
524-
}
525-
526-
if err := archive.Close(); err != nil {
527-
return nil, err
528-
}
529-
530-
fileBuffer := new(bytes.Buffer)
531-
m := io.MultiWriter(s, fileBuffer)
532-
533-
if _, err := io.Copy(m, buf); err != nil {
534-
return nil, err
535-
}
536-
file.Sum = hex.EncodeToString(s.Sum(nil))
537-
file.Buffer = bytes.NewReader(fileBuffer.Bytes())
538511
functions.Add(file.Name, file)
539512

540513
if observer != nil {
541514
if err := observer.OnSuccessfulStep(file); err != nil {
542515
return nil, err
543516
}
544517
}
545-
default:
546-
// Ignore this file
518+
case goDir(i):
519+
wkg := filepath.Join(functionDir, i.Name())
520+
goInfo, err := ioutil.ReadDir(wkg)
521+
if err != nil {
522+
return nil, err
523+
}
524+
525+
for _, gi := range goInfo {
526+
if m := gi.Mode(); m&0111 != 0 {
527+
{
528+
file, err := newFunctionFile(wkg, gi, "go")
529+
if err != nil {
530+
return nil, err
531+
}
532+
functions.Add(file.Name, file)
533+
534+
if observer != nil {
535+
if err := observer.OnSuccessfulStep(file); err != nil {
536+
return nil, err
537+
}
538+
}
539+
}
540+
}
541+
}
547542
}
548543
}
549544

550545
return functions, nil
551546
}
552547

548+
func newFunctionFile(dir string, i os.FileInfo, tp string) (*FileBundle, error) {
549+
file := &FileBundle{
550+
Name: strings.TrimSuffix(i.Name(), filepath.Ext(i.Name())),
551+
Runtime: tp,
552+
}
553+
554+
s := sha256.New()
555+
buf := new(bytes.Buffer)
556+
archive := zip.NewWriter(buf)
557+
fileHeader, err := archive.Create(i.Name())
558+
if err != nil {
559+
return nil, err
560+
}
561+
fileEntry, err := os.Open(filepath.Join(dir, i.Name()))
562+
if err != nil {
563+
return nil, err
564+
}
565+
defer fileEntry.Close()
566+
if _, err = io.Copy(fileHeader, fileEntry); err != nil {
567+
return nil, err
568+
}
569+
570+
if err := archive.Close(); err != nil {
571+
return nil, err
572+
}
573+
574+
fileBuffer := new(bytes.Buffer)
575+
m := io.MultiWriter(s, fileBuffer)
576+
577+
if _, err := io.Copy(m, buf); err != nil {
578+
return nil, err
579+
}
580+
file.Sum = hex.EncodeToString(s.Sum(nil))
581+
file.Buffer = bytes.NewReader(fileBuffer.Bytes())
582+
583+
return file, nil
584+
}
585+
586+
func jsFile(i os.FileInfo) bool {
587+
return filepath.Ext(i.Name()) == ".js"
588+
}
589+
590+
func goDir(i os.FileInfo) bool {
591+
return i.IsDir() && i.Name() == "well-known-go"
592+
}
593+
553594
func ignoreFile(rel string) bool {
554595
if strings.HasPrefix(rel, ".") || strings.Contains(rel, "/.") || strings.HasPrefix(rel, "__MACOS") {
555596
return !strings.HasPrefix(rel, ".well-known/")

0 commit comments

Comments
 (0)