mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
Fix lambda import (#605)
* Fix lambda import * more updates * more changes
This commit is contained in:
committed by
Travis Reeder
parent
cc4ff197e0
commit
d8871d1562
@@ -2,12 +2,12 @@
|
||||
|
||||
This is the exact same function that is in the AWS Lambda tutorial.
|
||||
|
||||
Other than a different runtime, this is no different than any other node example.
|
||||
Other than a different runtime, this is no different than any other node example.
|
||||
|
||||
To use the lambda-node runtime, use this `fn init` command:
|
||||
To use the lambda-nodejs4.3 runtime, use this `fn init` command:
|
||||
|
||||
```sh
|
||||
fn init --runtime lambda-node <DOCKER_HUB_USERNAME>/lambda-node
|
||||
fn init --runtime lambda-nodejs4.3 <DOCKER_HUB_USERNAME>/lambda-node
|
||||
fn build
|
||||
cat payload.json | fn run
|
||||
```
|
||||
|
||||
32
fn/common.go
32
fn/common.go
@@ -118,22 +118,22 @@ func exists(name string) bool {
|
||||
}
|
||||
|
||||
var acceptableFnRuntimes = map[string]string{
|
||||
"elixir": "iron/elixir",
|
||||
"erlang": "iron/erlang",
|
||||
"gcc": "iron/gcc",
|
||||
"go": "iron/go",
|
||||
"java": "iron/java",
|
||||
"leiningen": "iron/leiningen",
|
||||
"mono": "iron/mono",
|
||||
"node": "iron/node",
|
||||
"perl": "iron/perl",
|
||||
"php": "iron/php",
|
||||
"python": "iron/python:2",
|
||||
"ruby": "iron/ruby",
|
||||
"scala": "iron/scala",
|
||||
"rust": "corey/rust-alpine",
|
||||
"dotnet": "microsoft/dotnet:runtime",
|
||||
"lambda-node": "iron/functions-lambda:node",
|
||||
"elixir": "iron/elixir",
|
||||
"erlang": "iron/erlang",
|
||||
"gcc": "iron/gcc",
|
||||
"go": "iron/go",
|
||||
"java": "iron/java",
|
||||
"leiningen": "iron/leiningen",
|
||||
"mono": "iron/mono",
|
||||
"node": "iron/node",
|
||||
"perl": "iron/perl",
|
||||
"php": "iron/php",
|
||||
"python": "iron/python:2",
|
||||
"ruby": "iron/ruby",
|
||||
"scala": "iron/scala",
|
||||
"rust": "corey/rust-alpine",
|
||||
"dotnet": "microsoft/dotnet:runtime",
|
||||
"lambda-nodejs4.3": "iron/functions-lambda:nodejs4.3",
|
||||
}
|
||||
|
||||
const tplDockerfile = `FROM {{ .BaseImage }}
|
||||
|
||||
217
fn/lambda.go
217
fn/lambda.go
@@ -2,7 +2,6 @@ package main
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -17,16 +16,12 @@ import (
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
aws_lambda "github.com/aws/aws-sdk-go/service/lambda"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
lambdaImpl "github.com/iron-io/lambda/lambda"
|
||||
"github.com/urfave/cli"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
if len(runtimeCreateHandlers) != len(runtimeImportHandlers) {
|
||||
panic("incomplete implementation of runtime support")
|
||||
}
|
||||
|
||||
var runtimes = map[string]string{
|
||||
"nodejs4.3": "lambda-nodejs4.3",
|
||||
}
|
||||
|
||||
func lambda() cli.Command {
|
||||
@@ -38,20 +33,6 @@ func lambda() cli.Command {
|
||||
Name: "lambda",
|
||||
Usage: "create and publish lambda functions",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "create-function",
|
||||
Usage: `create Docker image that can run your Lambda function, where files are the contents of the zip file to be uploaded to AWS Lambda.`,
|
||||
ArgsUsage: "<name> <runtime> <handler> </path> [/paths...]",
|
||||
Action: create,
|
||||
Flags: flags,
|
||||
},
|
||||
{
|
||||
Name: "test-function",
|
||||
Usage: `runs local dockerized Lambda function and writes output to stdout.`,
|
||||
ArgsUsage: "<name>",
|
||||
Action: test,
|
||||
Flags: flags,
|
||||
},
|
||||
{
|
||||
Name: "aws-import",
|
||||
Usage: `converts an existing Lambda function to an image, where the function code is downloaded to a directory in the current working directory that has the same name as the Lambda function.`,
|
||||
@@ -100,87 +81,6 @@ func transcribeEnvConfig(configs []string) map[string]string {
|
||||
return c
|
||||
}
|
||||
|
||||
// create creates the Docker image for the Lambda function
|
||||
func create(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
functionName := args[0]
|
||||
runtime := args[1]
|
||||
handler := args[2]
|
||||
fileNames := args[3:]
|
||||
|
||||
files := make([]fileLike, 0, len(fileNames))
|
||||
opts := createImageOptions{
|
||||
Name: functionName,
|
||||
Base: fmt.Sprintf("iron/lambda-%s", runtime),
|
||||
Package: "",
|
||||
Handler: handler,
|
||||
OutputStream: newdockerJSONWriter(os.Stdout),
|
||||
RawJSONStream: true,
|
||||
Config: transcribeEnvConfig(c.StringSlice("config")),
|
||||
}
|
||||
|
||||
if handler == "" {
|
||||
return errors.New("No handler specified.")
|
||||
}
|
||||
|
||||
rh, ok := runtimeCreateHandlers[runtime]
|
||||
if !ok {
|
||||
return fmt.Errorf("unsupported runtime %v", runtime)
|
||||
}
|
||||
|
||||
if err := rh(fileNames, &opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, fileName := range fileNames {
|
||||
file, err := os.Open(fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
files = append(files, file)
|
||||
}
|
||||
|
||||
return createDockerfile(opts, files...)
|
||||
}
|
||||
|
||||
var runtimeCreateHandlers = map[string]func(filenames []string, opts *createImageOptions) error{
|
||||
"nodejs": func(filenames []string, opts *createImageOptions) error { return nil },
|
||||
"python2.7": func(filenames []string, opts *createImageOptions) error { return nil },
|
||||
"java8": func(filenames []string, opts *createImageOptions) error {
|
||||
if len(filenames) != 1 {
|
||||
return errors.New("Java Lambda functions can only include 1 file and it must be a JAR file.")
|
||||
}
|
||||
|
||||
if filepath.Ext(filenames[0]) != ".jar" {
|
||||
return errors.New("Java Lambda function package must be a JAR file.")
|
||||
}
|
||||
|
||||
opts.Package = filepath.Base(filenames[0])
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func test(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
if len(args) < 1 {
|
||||
return fmt.Errorf("Missing NAME argument")
|
||||
}
|
||||
functionName := args[0]
|
||||
|
||||
exists, err := lambdaImpl.ImageExists(functionName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !exists {
|
||||
return fmt.Errorf("Function %s does not exist.", functionName)
|
||||
}
|
||||
|
||||
payload := c.String("payload")
|
||||
// Redirect output to stdout.
|
||||
return lambdaImpl.RunImageWithPayload(functionName, payload)
|
||||
}
|
||||
|
||||
func awsImport(c *cli.Context) error {
|
||||
args := c.Args()
|
||||
|
||||
@@ -216,7 +116,7 @@ func awsImport(c *cli.Context) error {
|
||||
|
||||
opts := createImageOptions{
|
||||
Name: functionName,
|
||||
Base: fmt.Sprintf("iron/lambda-%s", *function.Configuration.Runtime),
|
||||
Base: runtimes[(*function.Configuration.Runtime)],
|
||||
Package: "",
|
||||
Handler: *function.Configuration.Handler,
|
||||
OutputStream: newdockerJSONWriter(os.Stdout),
|
||||
@@ -230,7 +130,7 @@ func awsImport(c *cli.Context) error {
|
||||
return fmt.Errorf("unsupported runtime %v", runtime)
|
||||
}
|
||||
|
||||
files, err := rh(functionName, tmpFileName, &opts)
|
||||
_, err = rh(functionName, tmpFileName, &opts)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -239,12 +139,18 @@ func awsImport(c *cli.Context) error {
|
||||
opts.Name = image
|
||||
}
|
||||
|
||||
return createDockerfile(opts, files...)
|
||||
fmt.Print("Creating func.yaml ... ")
|
||||
if err := createFunctionYaml(opts, functionName); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("OK")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
runtimeImportHandlers = map[string]func(functionName, tmpFileName string, opts *createImageOptions) ([]fileLike, error){
|
||||
"nodejs": basicImportHandler,
|
||||
"nodejs4.3": basicImportHandler,
|
||||
"python2.7": basicImportHandler,
|
||||
"java8": func(functionName, tmpFileName string, opts *createImageOptions) ([]fileLike, error) {
|
||||
fmt.Println("Found Java Lambda function. Going to assume code is a single JAR file.")
|
||||
@@ -268,20 +174,25 @@ func basicImportHandler(functionName, tmpFileName string, opts *createImageOptio
|
||||
return unzipAndGetTopLevelFiles(functionName, tmpFileName)
|
||||
}
|
||||
|
||||
func createFunctionYaml(opts createImageOptions) error {
|
||||
func createFunctionYaml(opts createImageOptions, functionName string) error {
|
||||
strs := strings.Split(opts.Name, "/")
|
||||
path := fmt.Sprintf("/%s", strs[1])
|
||||
|
||||
funcDesc := &funcfile{
|
||||
Name: opts.Name,
|
||||
Path: &path,
|
||||
Config: opts.Config,
|
||||
Name: opts.Name,
|
||||
Path: &path,
|
||||
Config: opts.Config,
|
||||
Version: "0.0.1",
|
||||
Runtime: &opts.Base,
|
||||
Cmd: opts.Handler,
|
||||
}
|
||||
|
||||
out, err := yaml.Marshal(funcDesc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(filepath.Join(opts.Name, "func.yaml"), out, 0644)
|
||||
|
||||
return ioutil.WriteFile(filepath.Join(functionName, "func.yaml"), out, 0644)
|
||||
}
|
||||
|
||||
type createImageOptions struct {
|
||||
@@ -301,90 +212,6 @@ type fileLike interface {
|
||||
|
||||
var errNoFiles = errors.New("No files to add to image")
|
||||
|
||||
// Create a Dockerfile that adds each of the files to the base image. The
|
||||
// expectation is that the base image sets up the current working directory
|
||||
// inside the image correctly. `handler` is set to be passed to node-lambda
|
||||
// for now, but we may have to change this to accomodate other stacks.
|
||||
func makeDockerfile(base string, pkg string, handler string, files ...fileLike) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintf(&buf, "FROM %s\n", base)
|
||||
|
||||
for _, file := range files {
|
||||
// FIXME(nikhil): Validate path, no parent paths etc.
|
||||
info, err := file.Stat()
|
||||
if err != nil {
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
fmt.Fprintf(&buf, "ADD [\"%s\", \"./%s\"]\n", info.Name(), info.Name())
|
||||
}
|
||||
|
||||
fmt.Fprint(&buf, "CMD [")
|
||||
if pkg != "" {
|
||||
fmt.Fprintf(&buf, "\"%s\", ", pkg)
|
||||
}
|
||||
// FIXME(nikhil): Validate handler.
|
||||
fmt.Fprintf(&buf, `"%s"`, handler)
|
||||
fmt.Fprint(&buf, "]\n")
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// Creates a docker image called `name`, using `base` as the base image.
|
||||
// `handler` is the runtime-specific name to use for a lambda invocation (i.e.
|
||||
// <module>.<function> for nodejs). `files` should be a list of files+dirs
|
||||
// *relative to the current directory* that are to be included in the image.
|
||||
func createDockerfile(opts createImageOptions, files ...fileLike) error {
|
||||
if len(files) == 0 {
|
||||
return errNoFiles
|
||||
}
|
||||
|
||||
df, err := makeDockerfile(opts.Base, opts.Package, opts.Handler, files...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Creating directory: %s ... ", opts.Name)
|
||||
if err := os.MkdirAll(opts.Name, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("OK")
|
||||
|
||||
fmt.Printf("Creating Dockerfile: %s ... ", filepath.Join(opts.Name, "Dockerfile"))
|
||||
outputFile, err := os.Create(filepath.Join(opts.Name, "Dockerfile"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("OK")
|
||||
|
||||
for _, f := range files {
|
||||
fstat, err := f.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Copying file: %s ... ", filepath.Join(opts.Name, fstat.Name()))
|
||||
src, err := os.Create(filepath.Join(opts.Name, fstat.Name()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := io.Copy(src, f); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("OK")
|
||||
}
|
||||
|
||||
if _, err = outputFile.Write(df); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Print("Creating func.yaml ... ")
|
||||
if err := createFunctionYaml(opts); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("OK")
|
||||
return nil
|
||||
}
|
||||
|
||||
type dockerJSONWriter struct {
|
||||
under io.Writer
|
||||
w io.Writer
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
set -ex
|
||||
|
||||
docker build -t iron/functions-lambda:node4.3 .
|
||||
docker build -t iron/functions-lambda:nodejs4.3 .
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
set -ex
|
||||
|
||||
./build.sh
|
||||
docker push iron/functions-lambda:node4.3
|
||||
docker push iron/functions-lambda:nodejs4.3
|
||||
|
||||
@@ -15,7 +15,7 @@ func GetLangHelper(lang string) LangHelper {
|
||||
return &RustLangHelper{}
|
||||
case "dotnet":
|
||||
return &DotNetLangHelper{}
|
||||
case "lambda-node":
|
||||
case "lambda-nodejs4.3":
|
||||
return &LambdaNodeHelper{}
|
||||
}
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user