Compare commits
12 Commits
0.8.76-alp
...
0.8.81-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c0182b29f | ||
|
|
02d55c7143 | ||
|
|
f343b537f1 | ||
|
|
a84e7da65f | ||
|
|
f3b64387cb | ||
|
|
e132435ff8 | ||
|
|
fb492fa6f7 | ||
|
|
159714491d | ||
|
|
64cbbc70bb | ||
|
|
d0559f627e | ||
|
|
0a6784e270 | ||
|
|
b6fd3c7e98 |
8
.github/workflows/docker.yml
vendored
8
.github/workflows/docker.yml
vendored
@@ -35,10 +35,10 @@ jobs:
|
|||||||
docker build -t metrue/fx-d-base:latest -f ./assets/dockerfiles/base/d/Dockerfile ./assets/dockerfiles/base/d
|
docker build -t metrue/fx-d-base:latest -f ./assets/dockerfiles/base/d/Dockerfile ./assets/dockerfiles/base/d
|
||||||
docker push metrue/fx-d-base:latest
|
docker push metrue/fx-d-base:latest
|
||||||
|
|
||||||
# - name: build and publish fx java image
|
- name: build and publish fx go image
|
||||||
# run: |
|
run: |
|
||||||
# docker build -t metrue/fx-go-base:latest -f ./assets/dockerfiles/base/java/Dockerfile ./assets/dockerfiles/base/java
|
docker build -t metrue/fx-go-base:latest -f ./assets/dockerfiles/base/go/Dockerfile ./assets/dockerfiles/base/go
|
||||||
# docker push metrue/fx-java-base:latest
|
docker push metrue/fx-go-base:latest
|
||||||
|
|
||||||
- name: build and publish fx node image
|
- name: build and publish fx node image
|
||||||
if: always()
|
if: always()
|
||||||
|
|||||||
@@ -32,3 +32,5 @@ brews:
|
|||||||
caveats: ""
|
caveats: ""
|
||||||
homepage: "https://github.com/metrue/fx"
|
homepage: "https://github.com/metrue/fx"
|
||||||
description: "fx, a simple but powerful Function as a Service build tools"
|
description: "fx, a simple but powerful Function as a Service build tools"
|
||||||
|
dependencies:
|
||||||
|
- docker
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -32,7 +32,7 @@ cli-test-ci:
|
|||||||
./scripts/test_cli.sh 'js'
|
./scripts/test_cli.sh 'js'
|
||||||
|
|
||||||
cli-test:
|
cli-test:
|
||||||
./scripts/test_cli.sh 'js rb py go php java d rs'
|
./scripts/test_cli.sh 'js rb py go php java d rs pl'
|
||||||
|
|
||||||
http-test:
|
http-test:
|
||||||
./scripts/http_test.sh
|
./scripts/http_test.sh
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ fx
|
|||||||
Poor man's function as a service.
|
Poor man's function as a service.
|
||||||
<br/>
|
<br/>
|
||||||

|

|
||||||
|

|
||||||
[](https://codecov.io/gh/metrue/fx)
|
[](https://codecov.io/gh/metrue/fx)
|
||||||
[](https://goreportcard.com/report/github.com/metrue/fx)
|
[](https://goreportcard.com/report/github.com/metrue/fx)
|
||||||
[](http://godoc.org/github.com/metrue/fx)
|
[](http://godoc.org/github.com/metrue/fx)
|
||||||
@@ -36,6 +37,7 @@ Feel free hacking fx to support the languages not listed. Welcome to tweet me [@
|
|||||||
| PHP | Supported | [@chlins](https://github.com/chlins)| [/examples/PHP](https://github.com/metrue/fx/tree/master/examples/functions/PHP) |
|
| PHP | Supported | [@chlins](https://github.com/chlins)| [/examples/PHP](https://github.com/metrue/fx/tree/master/examples/functions/PHP) |
|
||||||
| Julia | Supported | [@matbesancon](https://github.com/matbesancon)| [/examples/Julia](https://github.com/metrue/fx/tree/master/examples/functions/Julia) |
|
| Julia | Supported | [@matbesancon](https://github.com/matbesancon)| [/examples/Julia](https://github.com/metrue/fx/tree/master/examples/functions/Julia) |
|
||||||
| D | Supported | [@andre2007](https://github.com/andre2007)| [/examples/D](https://github.com/metrue/fx/tree/master/examples/functions/D) |
|
| D | Supported | [@andre2007](https://github.com/andre2007)| [/examples/D](https://github.com/metrue/fx/tree/master/examples/functions/D) |
|
||||||
|
| Perl | Supported | fx | [/examples/Perl](https://github.com/metrue/fx/tree/master/examples/functions/Perl) |
|
||||||
| R | Working on [need your help](https://github.com/metrue/fx/issues/31) | ||
|
| R | Working on [need your help](https://github.com/metrue/fx/issues/31) | ||
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|||||||
4
assets/dockerfiles/base/go/Dockerfile
vendored
Normal file
4
assets/dockerfiles/base/go/Dockerfile
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
FROM golang:latest
|
||||||
|
|
||||||
|
# dependency management
|
||||||
|
RUN go get github.com/gin-gonic/gin
|
||||||
10
assets/dockerfiles/base/perl/Dockerfile
vendored
Normal file
10
assets/dockerfiles/base/perl/Dockerfile
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
FROM alpine:3.4
|
||||||
|
MAINTAINER Mojolicious
|
||||||
|
|
||||||
|
ADD . .
|
||||||
|
COPY cpanfile /
|
||||||
|
ENV EV_EXTRA_DEFS -DEV_NO_ATFORK
|
||||||
|
|
||||||
|
RUN apk update && \
|
||||||
|
apk add perl perl-io-socket-ssl perl-dbd-pg perl-dev g++ make wget curl && \
|
||||||
|
curl -L https://cpanmin.us | perl - App::cpanminus && cpanm --installdeps . -M https://cpan.metacpan.org
|
||||||
2
assets/dockerfiles/base/perl/cpanfile
vendored
Normal file
2
assets/dockerfiles/base/perl/cpanfile
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
requires "EV";
|
||||||
|
requires "Mojolicious::Lite";
|
||||||
3
assets/dockerfiles/base/ruby/Dockerfile
vendored
Normal file
3
assets/dockerfiles/base/ruby/Dockerfile
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
FROM ruby:latest
|
||||||
|
|
||||||
|
RUN gem install sinatra
|
||||||
@@ -227,17 +227,27 @@ func (api *API) ListContainer(ctx context.Context, name string) ([]types.Service
|
|||||||
|
|
||||||
svs := make(map[string]types.Service)
|
svs := make(map[string]types.Service)
|
||||||
for _, container := range containers {
|
for _, container := range containers {
|
||||||
|
name := "UNKNOWN"
|
||||||
|
if len(container.Names) > 0 {
|
||||||
|
name = container.Names[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
port := -1
|
||||||
|
ip := "UNKNOWN"
|
||||||
|
if len(container.Ports) > 0 {
|
||||||
|
ip = container.Ports[0].IP
|
||||||
|
port = int(container.Ports[0].PublicPort)
|
||||||
|
}
|
||||||
|
|
||||||
// container name have extra forward slash
|
// container name have extra forward slash
|
||||||
// https://github.com/moby/moby/issues/6705
|
// https://github.com/moby/moby/issues/6705
|
||||||
if strings.HasPrefix(container.Names[0], fmt.Sprintf("/%s", name)) {
|
svs[container.Image] = types.Service{
|
||||||
svs[container.Image] = types.Service{
|
Name: name,
|
||||||
Name: container.Names[0],
|
Image: container.Image,
|
||||||
Image: container.Image,
|
ID: container.ID,
|
||||||
ID: container.ID,
|
Host: ip,
|
||||||
Host: container.Ports[0].IP,
|
Port: port,
|
||||||
Port: int(container.Ports[0].PublicPort),
|
State: container.State,
|
||||||
State: container.State,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
services := []types.Service{}
|
services := []types.Service{}
|
||||||
|
|||||||
36
examples/functions/Perl/README.md
vendored
Normal file
36
examples/functions/Perl/README.md
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# Make a Perl function a service with fx
|
||||||
|
|
||||||
|
Write a function like,
|
||||||
|
|
||||||
|
```perl
|
||||||
|
sub fx {
|
||||||
|
my $ctx = shift;
|
||||||
|
return 'hello fx'
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
||||||
|
```
|
||||||
|
|
||||||
|
then deploy it with `fx up` command,
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ fx up -p 8080:3000 func.pl
|
||||||
|
```
|
||||||
|
|
||||||
|
test it using `curl`
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ curl 127.0.0.1:8080
|
||||||
|
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
Connection: keep-alive
|
||||||
|
Content-Length: 11
|
||||||
|
Content-Type: text/plain; charset=utf-8
|
||||||
|
Date: Tue, 06 Aug 2019 15:58:41 GMT
|
||||||
|
|
||||||
|
hello fx
|
||||||
|
```
|
||||||
|
|
||||||
|
### ctx
|
||||||
|
|
||||||
|
The `ctx` object is exactly the [Controller](https://mojolicious.org/perldoc/Mojolicious/Controller) of [Mojolicious](https://mojolicious.org/perldoc/Mojolicious) framework.
|
||||||
6
examples/functions/Perl/func.pl
vendored
Normal file
6
examples/functions/Perl/func.pl
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
sub fx {
|
||||||
|
my $ctx = shift;
|
||||||
|
return 'hello fx'
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
||||||
2
fx.go
2
fx.go
@@ -16,7 +16,7 @@ import (
|
|||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
const version = "0.8.76"
|
const version = "0.8.81"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
go checkForUpdate()
|
go checkForUpdate()
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -22,7 +22,7 @@ require (
|
|||||||
github.com/gorilla/mux v1.7.3 // indirect
|
github.com/gorilla/mux v1.7.3 // indirect
|
||||||
github.com/imdario/mergo v0.3.7 // indirect
|
github.com/imdario/mergo v0.3.7 // indirect
|
||||||
github.com/logrusorgru/aurora v0.0.0-20191017060258-dc85c304c434
|
github.com/logrusorgru/aurora v0.0.0-20191017060258-dc85c304c434
|
||||||
github.com/metrue/go-ssh-client v0.0.0-20191209160027-5773243a8bc9
|
github.com/metrue/go-ssh-client v0.0.0-20191219103445-1f07b67e2b29
|
||||||
github.com/mholt/archiver v3.1.1+incompatible
|
github.com/mholt/archiver v3.1.1+incompatible
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -200,6 +200,8 @@ github.com/metrue/go-ssh-client v0.0.0-20191125030649-4ac058ee958b h1:JGD0sJ44Xz
|
|||||||
github.com/metrue/go-ssh-client v0.0.0-20191125030649-4ac058ee958b/go.mod h1:ERHOEBrDy6+8vfoJjjmhdmBpOzdvvP7bLtwYTTK6LOs=
|
github.com/metrue/go-ssh-client v0.0.0-20191125030649-4ac058ee958b/go.mod h1:ERHOEBrDy6+8vfoJjjmhdmBpOzdvvP7bLtwYTTK6LOs=
|
||||||
github.com/metrue/go-ssh-client v0.0.0-20191209160027-5773243a8bc9 h1:HHfMhG77ZLn3FOH3AGXW/F5RpAABVH6Fr5mVZZ97S6w=
|
github.com/metrue/go-ssh-client v0.0.0-20191209160027-5773243a8bc9 h1:HHfMhG77ZLn3FOH3AGXW/F5RpAABVH6Fr5mVZZ97S6w=
|
||||||
github.com/metrue/go-ssh-client v0.0.0-20191209160027-5773243a8bc9/go.mod h1:aPG/JtXTyLliKDDlkv+nzHbSbz2p2CBMAjNJRK4uhzY=
|
github.com/metrue/go-ssh-client v0.0.0-20191209160027-5773243a8bc9/go.mod h1:aPG/JtXTyLliKDDlkv+nzHbSbz2p2CBMAjNJRK4uhzY=
|
||||||
|
github.com/metrue/go-ssh-client v0.0.0-20191219103445-1f07b67e2b29 h1:ENoMPMVc24XbBuVZ7guZmTB/7MSd+vqOkImSu9UUiJw=
|
||||||
|
github.com/metrue/go-ssh-client v0.0.0-20191219103445-1f07b67e2b29/go.mod h1:aPG/JtXTyLliKDDlkv+nzHbSbz2p2CBMAjNJRK4uhzY=
|
||||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||||
github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU=
|
github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU=
|
||||||
github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU=
|
github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU=
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ func Build(ctx context.Contexter) (err error) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
workdir := fmt.Sprintf("/tmp/fx-%d", time.Now().Unix())
|
workdir := fmt.Sprintf("/tmp/fx-%d", time.Now().Unix())
|
||||||
|
if err := utils.EnsureDir(workdir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
defer os.RemoveAll(workdir)
|
defer os.RemoveAll(workdir)
|
||||||
|
|
||||||
// Cases supports
|
// Cases supports
|
||||||
@@ -66,11 +69,11 @@ func Build(ctx context.Contexter) (err error) {
|
|||||||
if err := docker.BuildImage(ctx.GetContext(), workdir, name); err != nil {
|
if err := docker.BuildImage(ctx.GetContext(), workdir, name); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
nameWithTag := name + ":latest"
|
nameWithTag := name + ":latest"
|
||||||
if err := docker.TagImage(ctx.GetContext(), name, nameWithTag); err != nil {
|
if err := docker.TagImage(ctx.GetContext(), name, nameWithTag); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Set("image", nameWithTag)
|
ctx.Set("image", nameWithTag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,8 +59,8 @@ func Provision(ctx context.Contexter) (err error) {
|
|||||||
if os.Getenv("KUBECONFIG") != "" {
|
if os.Getenv("KUBECONFIG") != "" {
|
||||||
cloudType = types.CloudTypeK8S
|
cloudType = types.CloudTypeK8S
|
||||||
conf = os.Getenv("KUBECONFIG")
|
conf = os.Getenv("KUBECONFIG")
|
||||||
|
ctx.Set("cloud_type", types.CloudTypeK8S)
|
||||||
}
|
}
|
||||||
ctx.Set("cloud_type", types.CloudTypeK8S)
|
|
||||||
|
|
||||||
if cloudType == types.CloudTypeDocker {
|
if cloudType == types.CloudTypeDocker {
|
||||||
var meta map[string]string
|
var meta map[string]string
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
5
packer/images/go/Dockerfile
vendored
5
packer/images/go/Dockerfile
vendored
@@ -1,11 +1,8 @@
|
|||||||
FROM golang:latest
|
FROM metrue/fx-go-base
|
||||||
|
|
||||||
COPY . /go/src/github.com/metrue/fx
|
COPY . /go/src/github.com/metrue/fx
|
||||||
WORKDIR /go/src/github.com/metrue/fx
|
WORKDIR /go/src/github.com/metrue/fx
|
||||||
|
|
||||||
# dependency management
|
|
||||||
RUN go get github.com/gin-gonic/gin
|
|
||||||
|
|
||||||
RUN go build -ldflags "-w -s" -o fx fx.go app.go
|
RUN go build -ldflags "-w -s" -o fx fx.go app.go
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|||||||
6
packer/images/perl/Dockerfile
vendored
Normal file
6
packer/images/perl/Dockerfile
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
FROM metrue/fx-perl-base
|
||||||
|
|
||||||
|
ADD . .
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
CMD ["perl", "app.pl", "daemon"]
|
||||||
17
packer/images/perl/app.pl
vendored
Normal file
17
packer/images/perl/app.pl
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
use Mojolicious::Lite;
|
||||||
|
|
||||||
|
require "./fx.pl";
|
||||||
|
|
||||||
|
get '/' => sub {
|
||||||
|
my $ctx = shift;
|
||||||
|
my $res = fx($ctx);
|
||||||
|
$ctx->render(json => $res);
|
||||||
|
};
|
||||||
|
|
||||||
|
post '/' => sub {
|
||||||
|
my $ctx = shift;
|
||||||
|
my $res = fx($ctx);
|
||||||
|
$ctx->render(json => $res);
|
||||||
|
};
|
||||||
|
|
||||||
|
app->start;
|
||||||
6
packer/images/perl/fx.pl
vendored
Normal file
6
packer/images/perl/fx.pl
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
sub fx {
|
||||||
|
my $ctx = shift;
|
||||||
|
return 'hello fx'
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
||||||
4
packer/images/ruby/Dockerfile
vendored
4
packer/images/ruby/Dockerfile
vendored
@@ -1,6 +1,4 @@
|
|||||||
FROM ruby:latest
|
FROM metrue/fx-ruby-base
|
||||||
|
|
||||||
RUN gem install sinatra
|
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|||||||
@@ -26,17 +26,23 @@ func Pack(output string, input ...string) error {
|
|||||||
return fmt.Errorf("source file or directory required")
|
return fmt.Errorf("source file or directory required")
|
||||||
}
|
}
|
||||||
|
|
||||||
var lang string
|
var language string
|
||||||
for _, f := range input {
|
for _, f := range input {
|
||||||
if utils.IsRegularFile(f) {
|
if utils.IsRegularFile(f) {
|
||||||
lang = langFromFileName(f)
|
lang, err := langFromFileName(f)
|
||||||
|
if err == nil {
|
||||||
|
language = lang
|
||||||
|
}
|
||||||
} else if utils.IsDir(f) {
|
} else if utils.IsDir(f) {
|
||||||
if err := filepath.Walk(f, func(path string, info os.FileInfo, err error) error {
|
if err := filepath.Walk(f, func(path string, info os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if utils.IsRegularFile(path) {
|
if utils.IsRegularFile(path) {
|
||||||
lang = langFromFileName(path)
|
lang, err := langFromFileName(path)
|
||||||
|
if err == nil {
|
||||||
|
language = lang
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
@@ -45,11 +51,11 @@ func Pack(output string, input ...string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if lang == "" {
|
if language == "" {
|
||||||
return fmt.Errorf("could not tell programe language of your input source codes")
|
return fmt.Errorf("could not tell programe language of your input source codes")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := restore(output, lang); err != nil {
|
if err := restore(output, language); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +85,7 @@ func Pack(output string, input ...string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !hasFxHandleFile(input...) {
|
if !hasFxHandleFile(input...) {
|
||||||
msg := `it requires a fx handle file when input is not a single file function, e.g.
|
msg := `it requires a fx handle file when input is not a single file function, e.g.
|
||||||
fx.go for Golang
|
fx.go for Golang
|
||||||
Fx.java for Java
|
Fx.java for Java
|
||||||
fx.php for PHP
|
fx.php for PHP
|
||||||
@@ -87,6 +93,7 @@ fx.py for Python
|
|||||||
fx.js for JavaScript or Node
|
fx.js for JavaScript or Node
|
||||||
fx.rb for Ruby
|
fx.rb for Ruby
|
||||||
fx.jl for Julia
|
fx.jl for Julia
|
||||||
|
fx.pl for Perl
|
||||||
fx.d for D`
|
fx.d for D`
|
||||||
return fmt.Errorf(msg)
|
return fmt.Errorf(msg)
|
||||||
}
|
}
|
||||||
@@ -154,54 +161,6 @@ func merge(dest string, input ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isHandler(name string) bool {
|
|
||||||
basename := filepath.Base(name)
|
|
||||||
nameWithoutExt := strings.TrimSuffix(basename, filepath.Ext(basename))
|
|
||||||
return nameWithoutExt == "fx" ||
|
|
||||||
nameWithoutExt == "Fx" || // Fx is for Java
|
|
||||||
nameWithoutExt == "mod" // mod.rs is for Rust
|
|
||||||
}
|
|
||||||
|
|
||||||
func langFromFileName(fileName string) string {
|
|
||||||
extLangMap := map[string]string{
|
|
||||||
".js": "node",
|
|
||||||
".go": "go",
|
|
||||||
".rb": "ruby",
|
|
||||||
".py": "python",
|
|
||||||
".php": "php",
|
|
||||||
".jl": "julia",
|
|
||||||
".java": "java",
|
|
||||||
".d": "d",
|
|
||||||
".rs": "rust",
|
|
||||||
}
|
|
||||||
return extLangMap[filepath.Ext(fileName)]
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasFxHandleFile(input ...string) bool {
|
|
||||||
var handleFile string
|
|
||||||
for _, file := range input {
|
|
||||||
if utils.IsRegularFile(file) && isHandler(file) {
|
|
||||||
handleFile = file
|
|
||||||
break
|
|
||||||
} else if utils.IsDir(file) {
|
|
||||||
if err := filepath.Walk(file, func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if utils.IsRegularFile(path) && isHandler(info.Name()) {
|
|
||||||
handleFile = path
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return handleFile != ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// PackIntoK8SConfigMapFile pack function a K8S config map file
|
// PackIntoK8SConfigMapFile pack function a K8S config map file
|
||||||
func PackIntoK8SConfigMapFile(dir string) (string, error) {
|
func PackIntoK8SConfigMapFile(dir string) (string, error) {
|
||||||
tree := map[string]string{}
|
tree := map[string]string{}
|
||||||
|
|||||||
70
packer/rules.go
Normal file
70
packer/rules.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package packer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"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 isHandler(name string) bool {
|
||||||
|
basename := filepath.Base(name)
|
||||||
|
nameWithoutExt := strings.TrimSuffix(basename, filepath.Ext(basename))
|
||||||
|
return nameWithoutExt == "fx" ||
|
||||||
|
nameWithoutExt == "Fx" || // Fx is for Java
|
||||||
|
nameWithoutExt == "mod" // mod.rs is for Rust
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasFxHandleFile(input ...string) bool {
|
||||||
|
var handleFile string
|
||||||
|
for _, file := range input {
|
||||||
|
if utils.IsRegularFile(file) && isHandler(file) {
|
||||||
|
handleFile = file
|
||||||
|
break
|
||||||
|
} else if utils.IsDir(file) {
|
||||||
|
if err := filepath.Walk(file, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if utils.IsRegularFile(path) && isHandler(info.Name()) {
|
||||||
|
handleFile = path
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return handleFile != ""
|
||||||
|
}
|
||||||
61
packer/rules_test.go
Normal file
61
packer/rules_test.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package packer
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestLangFromFileName(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
lang string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "a.js",
|
||||||
|
lang: "node",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "a.py",
|
||||||
|
lang: "python",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "a.go",
|
||||||
|
lang: "go",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "a.rb",
|
||||||
|
lang: "ruby",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "a.php",
|
||||||
|
lang: "php",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "a.jl",
|
||||||
|
lang: "julia",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "a.d",
|
||||||
|
lang: "d",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "a.rs",
|
||||||
|
lang: "rust",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "a.java",
|
||||||
|
lang: "java",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "a.pl",
|
||||||
|
lang: "perl",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
lang, err := langFromFileName(c.name)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if lang != c.lang {
|
||||||
|
t.Fatalf("should get %s but got %s", c.lang, lang)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ run() {
|
|||||||
local port=$2
|
local port=$2
|
||||||
# localhost
|
# localhost
|
||||||
$fx up --name ${service}_${lang} --port ${port} --healthcheck test/functions/func.${lang}
|
$fx up --name ${service}_${lang} --port ${port} --healthcheck test/functions/func.${lang}
|
||||||
$fx list # | jq ''
|
$fx list
|
||||||
$fx down ${service}_${lang} || true
|
$fx down ${service}_${lang} || true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ export_image() {
|
|||||||
if [[ "$DOCKER_REMOTE_HOST_ADDR" != "" ]];then
|
if [[ "$DOCKER_REMOTE_HOST_ADDR" != "" ]];then
|
||||||
cloud_name='fx-remote-docker-host'
|
cloud_name='fx-remote-docker-host'
|
||||||
$fx infra create --name ${cloud_name} --type docker --host ${DOCKER_REMOTE_HOST_USER}@${DOCKER_REMOTE_HOST_ADDR}
|
$fx infra create --name ${cloud_name} --type docker --host ${DOCKER_REMOTE_HOST_USER}@${DOCKER_REMOTE_HOST_ADDR}
|
||||||
$fx use ${cloud_name}
|
$fx infra use ${cloud_name}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
port=20000
|
port=20000
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ import (
|
|||||||
func HasDockerfile(dir string) bool {
|
func HasDockerfile(dir string) bool {
|
||||||
var dockerfile string
|
var dockerfile string
|
||||||
if err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
if err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
// nolint
|
// nolint
|
||||||
if info.Mode().IsRegular() && info.Name() == "Dockerfile" {
|
if info.Mode().IsRegular() && info.Name() == "Dockerfile" {
|
||||||
dockerfile = path
|
dockerfile = path
|
||||||
|
|||||||
Reference in New Issue
Block a user