Created
April 17, 2019 13:35
-
-
Save angelodlfrtr/e51ab4abde40a980bd904c353a2542e6 to your computer and use it in GitHub Desktop.
A go binary to autocompile and push go lambda function to aws lambda
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"archive/zip" | |
"bytes" | |
"encoding/json" | |
"flag" | |
"fmt" | |
"github.com/aws/aws-sdk-go/aws" | |
"github.com/aws/aws-sdk-go/aws/session" | |
"github.com/aws/aws-sdk-go/service/lambda" | |
"github.com/aws/aws-sdk-go/service/s3" | |
. "github.com/logrusorgru/aurora" | |
"io/ioutil" | |
"os" | |
"os/exec" | |
"path/filepath" | |
) | |
type RcConfig struct { | |
Name string `json:"name"` | |
Bucket string `json:"bucket"` | |
Region string `json:"region"` | |
} | |
func main() { | |
// =============================================================================================== | |
// FLAGS ========================================================================================= | |
// =============================================================================================== | |
// Load flags | |
functionPath := flag.String("path", ".", "Function path") | |
functionName := flag.String("name", "", "Function name") | |
s3Bucket := flag.String("bucket", "", "S3 bucket name") | |
region := flag.String("region", "", "AWS Region") | |
// Parse flags | |
flag.Parse() | |
// Get absolute path for lamlbda func | |
realFunctionPath, err := filepath.Abs(*functionPath) | |
if err != nil { | |
fmt.Println(Red(err.Error())) | |
os.Exit(1) | |
} | |
// Check dir exitence | |
if _, err = os.Stat(realFunctionPath); os.IsNotExist(err) { | |
fmt.Println(Red(fmt.Sprintf("Function path %s not exist", realFunctionPath))) | |
os.Exit(1) | |
} | |
// Get region | |
var awsRegion string | |
if len(*region) > 0 { | |
awsRegion = *region | |
} else { | |
awsRegion = os.Getenv("AWS_DEFAULT_REGION") | |
} | |
// =============================================================================================== | |
// PUSHRC ======================================================================================== | |
// =============================================================================================== | |
// Try to load .pushrc.json file in function | |
rcFilePath := fmt.Sprintf("%s/.pushrc.json", realFunctionPath) | |
var rcBytes []byte | |
rcBytes, err = ioutil.ReadFile(rcFilePath) | |
if err != nil { | |
//fmt.Println(Red(err.Error())) | |
Magenta(">> No rc file found") | |
} else { | |
// Load json | |
rcConfig := &RcConfig{} | |
err = json.Unmarshal(rcBytes, &rcConfig) | |
if err != nil { | |
fmt.Println(Red(err.Error())) | |
os.Exit(1) | |
} | |
// Append name | |
if len(rcConfig.Name) > 0 { | |
if len(*functionName) < 1 { | |
functionName = &rcConfig.Name | |
} | |
} | |
// Append bucket | |
if len(rcConfig.Bucket) > 0 { | |
if len(*s3Bucket) < 1 { | |
s3Bucket = &rcConfig.Bucket | |
} | |
} | |
// Append region | |
if len(rcConfig.Region) > 0 { | |
if len(awsRegion) < 1 { | |
awsRegion = rcConfig.Region | |
} | |
} | |
} | |
// =============================================================================================== | |
// VALIDATE ====================================================================================== | |
// =============================================================================================== | |
// Check function name | |
if len(*functionName) < 1 { | |
fmt.Println(Red("Function name required")) | |
fmt.Fprintf(os.Stderr, "Usage : pushlambdafungo [options]\n") | |
flag.PrintDefaults() | |
os.Exit(1) | |
} | |
if len(awsRegion) < 1 { | |
fmt.Println(Red("AWS region required")) | |
fmt.Fprintf(os.Stderr, "Usage : pushlambdafungo [options]\n") | |
flag.PrintDefaults() | |
} | |
fmt.Println(">> Run pushlambdafungo for function", Green(realFunctionPath)) | |
fmt.Println(">> Function name :", Green(*functionName)) | |
fmt.Println(">> AWS Region :", Green(awsRegion)) | |
fmt.Println(">> S3 Bucket :", Green(*s3Bucket)) | |
// =============================================================================================== | |
// BUILD ========================================================================================= | |
// =============================================================================================== | |
fmt.Println(">> Building target function ...") | |
// Cross compile function for lambda env | |
compileCmd := exec.Command( | |
"go", | |
"build", | |
"-o", | |
fmt.Sprintf("%s/main", realFunctionPath), | |
fmt.Sprintf("%s/main.go", realFunctionPath), | |
) | |
// Append correct env | |
compileCmd.Env = os.Environ() | |
compileCmd.Env = append(compileCmd.Env, "GOOS=linux") | |
var compileOut []byte | |
compileOut, err = compileCmd.CombinedOutput() | |
if err != nil { | |
fmt.Println(err.Error()) | |
fmt.Println(string(compileOut)) | |
os.Exit(1) | |
} | |
fmt.Println(">> Build target function", Green("success")) | |
// =============================================================================================== | |
// ZIP =========================================================================================== | |
// =============================================================================================== | |
fmt.Println(">> Zip generated binary ...") | |
// Create zip buffer | |
zipBuf := new(bytes.Buffer) | |
// Create zip writer | |
zip := zip.NewWriter(zipBuf) | |
// Create zip file (will contain out binary) | |
zipF, _ := zip.Create("main") | |
// Read compiled binary as array of byte | |
binaryContent, err := ioutil.ReadFile(fmt.Sprintf("%s/main", realFunctionPath)) | |
if err != nil { | |
fmt.Println(Red(err.Error())) | |
os.Exit(1) | |
} | |
// Add compiled bynary content to zip file | |
zipF.Write(binaryContent) | |
// Close zip writer | |
zip.Close() | |
fmt.Println(">> Zip generated binary", Green("success")) | |
// =============================================================================================== | |
// S3 UPLOAD ===================================================================================== | |
// =============================================================================================== | |
fmt.Println(">> Push zip archive to s3 bucket", *s3Bucket, "...") | |
// Create AWS session | |
sess := session.Must(session.NewSession(&aws.Config{ | |
Region: aws.String(awsRegion), | |
})) | |
// Create S3 Client | |
s3Client := s3.New(sess) | |
// Create io reader from zip buffer | |
zipReader := bytes.NewReader(zipBuf.Bytes()) | |
// Put object params | |
s3Input := &s3.PutObjectInput{ | |
Bucket: aws.String(*s3Bucket), | |
Key: aws.String(fmt.Sprintf("%s.zip", *functionName)), | |
Body: aws.ReadSeekCloser(zipReader), | |
} | |
// Create object in s3 | |
_, err = s3Client.PutObject(s3Input) | |
if err != nil { | |
fmt.Println(Red(err.Error())) | |
os.Exit(1) | |
} | |
fmt.Println(">> Push zip archive to s3 bucket", *s3Bucket, Green("success")) | |
// =============================================================================================== | |
// UPDATE FUNCTION CODE ========================================================================== | |
// =============================================================================================== | |
fmt.Println(">> Update aws lambda function code ...") | |
lambdaClient := lambda.New(sess) | |
updateFuncCodeInput := &lambda.UpdateFunctionCodeInput{ | |
FunctionName: aws.String(*functionName), | |
Publish: aws.Bool(false), | |
S3Bucket: aws.String(*s3Bucket), | |
S3Key: aws.String(fmt.Sprintf("%s.zip", *functionName)), | |
} | |
_, err = lambdaClient.UpdateFunctionCode(updateFuncCodeInput) | |
if err != nil { | |
fmt.Println(Red(err.Error())) | |
os.Remove(fmt.Sprintf("%s/main", *functionPath)) | |
os.Exit(1) | |
} | |
fmt.Println(">> Update aws lambda function code", Green("success")) | |
// =============================================================================================== | |
// REMOVE GENERATED BINARY ======================================================================= | |
// =============================================================================================== | |
err = os.Remove(fmt.Sprintf("%s/main", *functionPath)) | |
if err != nil { | |
fmt.Println(Red(err.Error())) | |
os.Exit(1) | |
} | |
// =============================================================================================== | |
// DONE ========================================================================================== | |
// =============================================================================================== | |
fmt.Println(">> All done :)") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment