Fn and deps (#475)

This commit is contained in:
Minghe
2020-03-11 08:59:47 +08:00
committed by GitHub
parent 871bb29dbe
commit 302877d4b4
8 changed files with 110 additions and 105 deletions

View File

@@ -8,6 +8,7 @@ import (
"github.com/gobuffalo/packd"
"github.com/gobuffalo/packr/v2"
"github.com/metrue/fx/constants"
"github.com/metrue/fx/utils"
)
@@ -19,22 +20,9 @@ type Bundler interface {
// IsHandler check if it's handle file
func IsHandler(name string, lang string) bool {
extLangMapping := map[string]string{
".js": "node",
".go": "go",
".rb": "ruby",
".py": "python",
".php": "php",
".jl": "julia",
".java": "java",
".d": "d",
".rs": "rust",
".pl": "perl",
}
basename := filepath.Base(name)
nameWithoutExt := strings.TrimSuffix(basename, filepath.Ext(basename))
if extLangMapping[filepath.Ext(basename)] != lang {
if constants.ExtLangMapping[filepath.Ext(basename)] != lang {
return false
}

15
constants/languages.go Normal file
View File

@@ -0,0 +1,15 @@
package constants
// ExtLangMapping file extension mapping with programming language
var ExtLangMapping = map[string]string{
".js": "node",
".go": "go",
".rb": "ruby",
".py": "python",
".php": "php",
".jl": "julia",
".java": "java",
".d": "d",
".rs": "rust",
".pl": "perl",
}

View File

@@ -23,15 +23,14 @@ func BuildImage(ctx context.Contexter) (err error) {
workdir := fmt.Sprintf("/tmp/fx-%d", time.Now().Unix())
defer os.RemoveAll(workdir)
sources := ctx.Get("sources").([]string)
fn := ctx.Get("fn").(string)
deps := ctx.Get("deps").([]string)
language := ctx.Get("language").(string)
if len(sources) == 0 {
return fmt.Errorf("source file/directory of function required")
}
if err := bundle.Bundle(workdir, language, sources[0], sources[1:]...); err != nil {
if err := bundle.Bundle(workdir, language, fn, deps...); err != nil {
return err
}
if err := hook.RunBeforeBuildHook(workdir); err != nil {
return err
}
@@ -48,15 +47,15 @@ func BuildImage(ctx context.Contexter) (err error) {
// ExportImage export service's code into a directory
func ExportImage(ctx context.Contexter) (err error) {
outputDir := ctx.Get("output").(string)
sources := ctx.Get("sources").([]string)
fn := ctx.Get("fn").(string)
deps := ctx.Get("deps").([]string)
language := ctx.Get("language").(string)
if len(sources) == 0 {
return fmt.Errorf("source file/directory of function required")
}
if err := bundle.Bundle(outputDir, language, sources[0], sources[1:]...); err != nil {
if err := bundle.Bundle(outputDir, language, fn, deps...); err != nil {
return err
}
if err := hook.RunBeforeBuildHook(outputDir); err != nil {
return err
}

View File

@@ -39,20 +39,18 @@ func Build(ctx context.Contexter) (err error) {
// fx up func.js helper.js ./lib/
// When only one directory given and there is a Dockerfile in given directory, treat it as a containerized project and skip packing
sources := ctx.Get("sources").([]string)
fn := ctx.Get("fn").(string)
deps := ctx.Get("deps").([]string)
language := ctx.Get("language").(string)
if len(sources) == 0 {
return fmt.Errorf("source file/directory of function required")
}
if err := bundle.Bundle(workdir, language, sources[0], sources[1:]...); err != nil {
if err := bundle.Bundle(workdir, language, fn, deps...); err != nil {
return err
}
if err := hook.RunBeforeBuildHook(workdir); err != nil {
return err
}
cloudType := ctx.Get("cloud_type").(string)
name := ctx.Get("name").(string)
if cloudType == types.CloudTypeK8S {

View File

@@ -2,70 +2,20 @@ package middlewares
import (
"fmt"
"os"
"path/filepath"
"github.com/metrue/fx/constants"
"github.com/metrue/fx/context"
"github.com/metrue/fx/utils"
)
// ExtLangMapping file extension mapping with programming language
var ExtLangMapping = map[string]string{
".js": "node",
".go": "go",
".rb": "ruby",
".py": "python",
".php": "php",
".jl": "julia",
".java": "java",
".d": "d",
".rs": "rust",
".pl": "perl",
}
func langFromFileName(fileName string) (string, error) {
if fileName == "" {
return "", fmt.Errorf("file name should not be empty")
}
ext := filepath.Ext(fileName)
lang, ok := ExtLangMapping[ext]
if !ok {
return "", fmt.Errorf("could not find corresponse programming language for file extension %s", ext)
}
return lang, nil
}
// Language to find out what language of function is
func Language() func(ctx context.Contexter) (err error) {
return func(ctx context.Contexter) error {
sources := ctx.Get("sources").([]string)
var language string
for _, f := range sources {
if utils.IsRegularFile(f) {
lang, err := langFromFileName(f)
if err == nil {
language = lang
}
} else if utils.IsDir(f) {
if err := filepath.Walk(f, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if utils.IsRegularFile(path) {
lang, err := langFromFileName(path)
if err == nil {
language = lang
}
}
return nil
}); err != nil {
return err
}
}
}
if language == "" {
return fmt.Errorf("could not tell programing language of your source codes")
fn := ctx.Get("fn").(string)
ext := filepath.Ext(fn)
language, ok := constants.ExtLangMapping[ext]
if !ok {
return fmt.Errorf("%s not supported yet", ext)
}
ctx.Set("language", language)
return nil

View File

@@ -0,0 +1,19 @@
package middlewares
import (
"testing"
"github.com/golang/mock/gomock"
mockCtx "github.com/metrue/fx/context/mocks"
)
func TestLanguage(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
ctx := mockCtx.NewMockContexter(ctrl)
ctx.EXPECT().Get("fn").Return("/tmp/fx.js")
ctx.EXPECT().Set("language", "node")
if err := Language()(ctx); err != nil {
t.Fatal(err)
}
}

View File

@@ -14,15 +14,23 @@ func Parse(action string) func(ctx context.Contexter) (err error) {
cli := ctx.GetCliContext()
switch action {
case "up":
sources := []string{}
for _, s := range cli.Args() {
if utils.IsDir(s) || utils.IsRegularFile(s) {
sources = append(sources, s)
} else {
return fmt.Errorf("no such file or directory: %s", s)
if !cli.Args().Present() {
return fmt.Errorf("no function given")
}
if !utils.IsRegularFile(cli.Args().First()) {
return fmt.Errorf("invalid function source file: %s", cli.Args().First())
}
ctx.Set("fn", cli.Args().First())
deps := []string{}
for ind, s := range cli.Args() {
if ind != 0 {
deps = append(deps, s)
}
}
ctx.Set("sources", sources)
ctx.Set("deps", deps)
name := cli.String("name")
ctx.Set("name", name)
port := cli.Int("port")
@@ -45,22 +53,46 @@ func Parse(action string) func(ctx context.Contexter) (err error) {
format := cli.String("format")
ctx.Set("format", format)
case "image_build":
sources := []string{}
for _, s := range cli.Args() {
sources = append(sources, s)
if !cli.Args().Present() {
return fmt.Errorf("no function given")
}
ctx.Set("sources", sources)
if !utils.IsRegularFile(cli.Args().First()) {
return fmt.Errorf("invalid function source file: %s", cli.Args().First())
}
ctx.Set("fn", cli.Args().First())
deps := []string{}
for ind, s := range cli.Args() {
if ind != 0 {
deps = append(deps, s)
}
}
ctx.Set("deps", deps)
tag := cli.String("tag")
if tag == "" {
tag = uuid.New().String()
}
ctx.Set("tag", tag)
case "image_export":
sources := []string{}
for _, s := range cli.Args() {
sources = append(sources, s)
if !cli.Args().Present() {
return fmt.Errorf("no function given")
}
ctx.Set("sources", sources)
if !utils.IsRegularFile(cli.Args().First()) {
return fmt.Errorf("invalid function source file: %s", cli.Args().First())
}
ctx.Set("fn", cli.Args().First())
deps := []string{}
for ind, s := range cli.Args() {
if ind != 0 {
deps = append(deps, s)
}
}
ctx.Set("deps", deps)
outputDir := cli.String("output")
if outputDir == "" {
return fmt.Errorf("output directory required")

View File

@@ -1,6 +1,7 @@
package middlewares
import (
"io/ioutil"
"os"
"testing"
@@ -32,18 +33,21 @@ func TestParse(t *testing.T) {
ctx := mockCtx.NewMockContexter(ctrl)
argset := flag.NewFlagSet("test", 0)
cli := cli.NewContext(nil, argset, nil)
pwd, err := os.Getwd()
fd, err := ioutil.TempFile("", "fx_func_*.js")
if err != nil {
t.Fatal(err)
}
argset.Parse([]string{pwd})
defer os.Remove(fd.Name())
argset.Parse([]string{fd.Name()})
ctx.EXPECT().GetCliContext().Return(cli)
ctx.EXPECT().Set("sources", []string{pwd})
ctx.EXPECT().Set("fn", fd.Name())
ctx.EXPECT().Set("deps", []string{})
ctx.EXPECT().Set("name", "")
ctx.EXPECT().Set("port", 0)
ctx.EXPECT().Set("force", false)
if err := Parse("up")(ctx); err != nil {
t.Fatal("should got file or directory not existed error")
t.Fatal(err)
}
})
}