Compare commits

...

368 Commits

Author SHA1 Message Date
Minghe
047fac2a0a Docker image build in Cluster (#327)
* * image build in cluster now
  use InitContainer to do the image building inside pods, which invoke
  docker again node's docker daemon
* create a docker build image tool fx/contrib/docker_packer
* clean up no need env in GitHub action workflow
* bump version
2019-10-16 23:37:52 +08:00
Minghe
1cb68766f7 fix version parse (#324) 2019-10-14 20:39:47 +08:00
Minghe Huang
91fd5dc59f bump version 2019-10-14 16:49:29 +08:00
Changxin Miao
184235acb2 Automatically notify user of new release (#317)
* Automatically notify user of new release

Signed-off-by: Changxin Miao <mcx_221@foxmail.com>

* Update naming convention
2019-10-14 13:38:07 +08:00
Minghe
aa49a59feb * kuberntes has some limitation on naming,By convention, the names of Kubernetes resources should be up to maximum length of 253 characters and consist of lower case alphanumeric characters, -, and ., but certain resources have more specific restrictions. (#322)
* skip run deploy when KUBECONFIG, DOCKER_USERNAME, and DOCKER_PASSWORD is not ready
2019-10-14 13:21:27 +08:00
Minghe
c9d382d903 Skip test when no credentials ready (#320)
* Since fork PR build could not read secrets of GitHub action,
https://github.community/t5/GitHub-Actions/Allow-secrets-to-be-shared-with-trusted-Actions/td-p/34278
So skip test when its credentials are nod ready

* skip deploy test when no DOCKER_USERNAME and DOCKER_PASSWORD found
2019-10-14 12:37:06 +08:00
Changxin Miao
81e18e5b0d Deployment selector should be immutable (#316)
Signed-off-by: Changxin Miao <mcx_221@foxmail.com>
2019-10-14 11:55:08 +08:00
Minghe
3882f843bf fix lint issue (#319) 2019-10-14 10:20:12 +08:00
Minghe
293481f081 release 0.7.3 (#311) 2019-10-12 21:41:49 +08:00
Minghe
c12d967ced fix typo (#310) 2019-10-12 21:09:06 +08:00
Minghe
b2a62cbd94 * create a deployment instead of create a pod directly (#308)
* remove host port expose to fix the port ocuppied issue
2019-10-12 20:41:02 +08:00
Minghe
536b757602 fix branch match issue (#306) 2019-10-10 19:51:07 +08:00
Minghe
ddff53fff2 improve installation script (#304)
* improve installation script and enable installation test in CI
* disable mac installation check
2019-10-10 14:31:58 +08:00
Minghe
ae87215cfb Auto release by goreleaser (#303) 2019-10-10 13:10:18 +08:00
Minghe
90d7ec88f0 disable julia in test, since the HttpParser is not in registry (#301)
* disable julia in test, since the HttpParser is not in registry

* fix typo
2019-10-09 17:24:50 +08:00
Minghe
697277e1bb longger timeout for golang linter (#300) 2019-10-09 10:53:00 +08:00
Minghe
a17126c713 fix typo 2019-10-09 01:26:17 +08:00
Minghe
2c35262b9e fix workflow 2019-10-09 01:23:31 +08:00
Minghe
017a34c13c fix typo 2019-10-09 01:05:33 +08:00
Minghe
bf8885e91a bump version and add depend on jobs (#299) 2019-10-09 01:02:02 +08:00
Minghe
e04ed119a6 fix missing env 2019-10-09 00:45:21 +08:00
Minghe
551e4986d3 fix typo 2019-10-09 00:39:33 +08:00
Minghe
fa05603599 use go 1.12.0 (#298) 2019-10-09 00:24:26 +08:00
Minghe
4826726d65 fix typo (#297) 2019-10-09 00:14:40 +08:00
Minghe
f33b3560ce fix typo (#296) 2019-10-09 00:07:42 +08:00
Minghe
2e6ec2f8a2 simple (#295) 2019-10-09 00:03:20 +08:00
Minghe
d821b46744 add releaser (#294) 2019-10-08 23:50:12 +08:00
Minghe
dab52aae5a no need to commit (#293) 2019-10-08 23:35:14 +08:00
Minghe
89ebf19859 use https://github.com/goreleaser/goreleaser-action/blob/master/.github/workflows/release.yml as refer (#292) 2019-10-08 23:24:12 +08:00
Minghe
d3d1a684cb update readme (#288) 2019-10-08 23:13:41 +08:00
Minghe
2f1ed88dc6 add releaser (#290) 2019-10-08 23:12:51 +08:00
Minghe
a7cfa99643 move docker HTTP client code into container_runtimes folder (#289) 2019-10-08 23:00:53 +08:00
Minghe
3454ec0fdb Deploy function on bare docker. (#286) 2019-10-08 11:08:01 +08:00
Minghe
f70ef1c406 fx on k8s (#278) 2019-10-05 18:49:25 +08:00
Sebastian Hafner
a5db158fe5 exclude markdown file extraction from install script (#283) 2019-10-01 18:25:46 +08:00
Minghe
a4d44a4fc0 add service api 2019-09-28 15:42:51 +08:00
Minghe
6b25cac002 add pod delete api (#270) 2019-09-28 14:28:42 +08:00
Minghe
af28f4d345 simplify ci workflow (#272) 2019-09-28 14:09:25 +08:00
Minghe
c540163e5f skip images assert (#271) 2019-09-28 11:37:48 +08:00
Minghe
ae3d76868d init k8s client (#268) 2019-09-27 18:50:33 +08:00
Minghe
bea48d26b3 setup kind and k8s (#269) 2019-09-27 17:36:43 +08:00
Minghe
0196c11793 bump version 2019-09-26 09:05:49 +08:00
Minghe
ab127a36ff support image operation, (#266)
* fx image build, build a function into a image which a API service handle with function
* fx image export, export service into a directory, for easy debug, we
  can just go the directory to do everything with Docker cli
2019-09-25 20:06:49 +08:00
Minghe
24a9fb1c35 enable default network fx-net (#262) 2019-09-22 21:41:52 +08:00
Minghe
9c2f14ce27 add network api (#261) 2019-09-22 20:26:07 +08:00
Vadim
ffa37ac77b Fix typo (Rust -> JavaScript) (#258) 2019-09-17 08:28:33 +08:00
Minghe
d21e3cfb4a check if port is in valid range (#257) 2019-09-14 15:03:52 +08:00
Minghe
199339bdfa show error message of container start issue (#256) 2019-09-14 14:24:56 +08:00
dependabot-preview[bot]
0d01728e20 Bump github.com/urfave/cli from 1.21.0 to 1.22.1 (#254)
Bumps [github.com/urfave/cli](https://github.com/urfave/cli) from 1.21.0 to 1.22.1.
- [Release notes](https://github.com/urfave/cli/releases)
- [Changelog](https://github.com/urfave/cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/urfave/cli/compare/v1.21.0...v1.22.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-13 11:28:44 +08:00
Minghe
e1b752407e disable autorelease since it's not working as expected, and i have no time to check (#252) 2019-08-31 19:03:35 +08:00
Minghe
73f3a3853f move up handle to handlers (#247)
* * done move handle codes to handlers pkg
* support force deploy a function

* fix remote host issue
2019-08-31 18:55:58 +08:00
Russtopia
2b7176201e Updated README.md for 0.5.4 (#251)
Instructions here didn't work with latest pull (0.5.4).
2019-08-31 10:01:21 +08:00
Minghe
37b2733dcf fix container naming missing issue (#250)
* fix container naming missing issue

* bump version
2019-08-30 22:58:23 +08:00
dependabot-preview[bot]
33943c83f1 Bump github.com/stretchr/testify from 1.3.0 to 1.4.0 (#248)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.3.0 to 1.4.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.3.0...v1.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-18 09:00:39 +08:00
Minghe
7d3cc8f8d0 Setup CI via GitHub actions (#241)
* Update go.yml

* provision docker

* fix use

* fix use

* migration to workflows

* fix dep

* refactor workflows

* setup golang env

* fix path issue

* fix path issue

* Fix

* clean up

* provision docker

* start fx agent

* check

* check

* Squashed commit of the following:

commit c7f50a3256164573f1f7910c4b79729c91f77af7
Author: Minghe Huang <h.minghe@gmail.com>
Date:   Mon Aug 12 08:13:54 2019 +0800

    update

commit e5ba0ea5af
Author: Minghe Huang <h.minghe@gmail.com>
Date:   Sun Aug 11 23:53:38 2019 +0800

    test

commit aec09957f9
Author: Minghe Huang <h.minghe@gmail.com>
Date:   Sun Aug 11 23:38:37 2019 +0800

    add unit test

commit 59ac78a112
Author: Minghe Huang <h.minghe@gmail.com>
Date:   Sun Aug 11 22:52:51 2019 +0800

    refactor api

* Squashed commit of the following:

commit caa7e06fee72f345c6fad742f30a740f1c3de04d
Author: Minghe Huang <h.minghe@gmail.com>
Date:   Mon Aug 12 13:42:54 2019 +0800

    refactor api

commit a384c6c023325da36fa54818c1c69673c439f8af
Author: Minghe Huang <h.minghe@gmail.com>
Date:   Mon Aug 12 09:58:21 2019 +0800

    move packer

* disable test

* manage dep
2019-08-12 23:17:14 +08:00
Minghe
278652559a Enable health check for service (#242) 2019-08-11 12:09:11 +08:00
Minghe
87831d23f8 upgrade go-ssh-client to include latest fix (#239) 2019-08-10 14:59:41 +08:00
Minghe
4ace1d285f update readme (#238) 2019-08-10 13:47:55 +08:00
Minghe
d1191c2c85 update README (#237) 2019-08-10 13:39:55 +08:00
Minghe
2f238e9ce0 manage infrastructure (currently only suport host management) of fx (#233) 2019-08-10 11:54:40 +08:00
dependabot-preview[bot]
8fe146dabb Bump github.com/apex/log from 1.1.0 to 1.1.1 (#234)
Bumps [github.com/apex/log](https://github.com/apex/log) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/apex/log/releases)
- [Changelog](https://github.com/apex/log/blob/master/History.md)
- [Commits](https://github.com/apex/log/compare/v1.1.0...v1.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-09 19:13:03 +08:00
dependabot-preview[bot]
5c83a05054 Bump github.com/golang/mock from 1.2.0 to 1.3.1 (#235)
Bumps [github.com/golang/mock](https://github.com/golang/mock) from 1.2.0 to 1.3.1.
- [Release notes](https://github.com/golang/mock/releases)
- [Commits](https://github.com/golang/mock/compare/v1.2.0...1.3.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-09 19:12:09 +08:00
dependabot-preview[bot]
f0c4a8f159 Bump github.com/urfave/cli from 1.20.0 to 1.21.0 (#236)
Bumps [github.com/urfave/cli](https://github.com/urfave/cli) from 1.20.0 to 1.21.0.
- [Release notes](https://github.com/urfave/cli/releases)
- [Changelog](https://github.com/urfave/cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/urfave/cli/compare/v1.20.0...v1.21.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-09 18:09:57 +08:00
Minghe Huang
edb6bbc585 Squashed commit of the following:
commit 44fee6b8cfb231c16bafaa9c39228aafc8a74e5d
Author: Minghe Huang <h.minghe@gmail.com>
Date:   Fri Aug 9 10:56:03 2019 +0800

    add PR template
2019-08-09 10:56:21 +08:00
Minghe
e301d2d54f context of fx function (#223) 2019-08-09 09:10:49 +08:00
Minghe Huang
474cb26920 Squashed commit of the following:
commit 2f4d229b1ebabc3839fc1fbbe5444498fd929c80
Author: Minghe Huang <h.minghe@gmail.com>
Date:   Sun Aug 4 22:51:03 2019 +0800

    output log when debug
2019-08-04 22:51:18 +08:00
Minghe
8c962bf31a add redis (#222) 2019-08-04 21:45:43 +08:00
Minghe
c8c4d69b57 release v0.4.0 (#220) 2019-07-29 09:31:47 +08:00
Minghe
61c151ef11 enable remote host provision and deploy (#216)
* 1. support provision a remote host
2. support deploy function to a remote host
3. support hosts management now

features:
* fx provision - provision on default host
* fx host - manage hosts
2019-07-29 09:27:34 +08:00
Minghe Huang
7d709d8f19 Squashed commit of the following:
commit 9b7cf0af05a0a248b6c200aef20a597ca212b88a
Author: Minghe Huang <h.minghe@gmail.com>
Date:   Mon Jul 22 22:24:59 2019 +0800

    use github default token
2019-07-22 22:25:28 +08:00
Minghe
9f14931d1f multiple workflow in one source file (#214) 2019-07-22 21:14:34 +08:00
Minghe
6a7d7b2353 move goreleaser to github action(#213) 2019-07-22 14:26:51 +08:00
Minghe
52ffb3ef25 vendor deps (#212) 2019-07-22 11:11:20 +08:00
Minghe
33ca880d73 build first before release (#211) 2019-07-22 10:31:36 +08:00
Minghe Huang
8b13442a15 Squashed commit of the following:
commit afe4a1291624b0110519f4f6b3b79a057a10762b
Author: Minghe Huang <h.minghe@gmail.com>
Date:   Mon Jul 22 00:28:32 2019 +0800

    bump version
2019-07-22 00:28:55 +08:00
Minghe
efe7ad5b00 run test concurrency (#208)
* run test concurrency

* enable cli test in PR
2019-07-22 00:26:59 +08:00
Minghe
b9cf6c9a07 add fx-golang-base (#207)
* * Create fx-go-base image
* Use func(ctx *gin.Context) as handle function

* enable pull golang base image
2019-07-21 22:39:11 +08:00
Minghe
7da8695b1b fix docker proxy startup init issue (#205) 2019-07-21 20:51:27 +08:00
Minghe
6c569458a1 enable golangci-lint (#204)
* enable golangci-lint

* add golangci config

* enable lint and fix lint issues
2019-07-21 18:38:59 +08:00
Minghe
fef6580134 replace dep with go mod (#203) 2019-07-21 17:52:46 +08:00
Minghe
fdae35cb37 fix rust build (#201) 2019-07-21 14:06:14 +08:00
Minghe
6180c62d31 fetch and context for handle function (#199)
* Add `node-fetch` to node base image
* Pass `koa` context as the second parameter for node handler function
* bump version
2019-07-21 13:21:28 +08:00
Minghe
295745b3d6 docs(naming): fix install cmd (#192) 2019-03-27 19:23:09 +08:00
Minghe
32f4fab154 docs(*): update readme (#190)
* docs(*): update readme

* feat(svg): update docs

* feat(svg): update docs

* docs(*): clean up

* docs(*): clean up
2019-03-23 11:48:04 +08:00
Minghe
7859f57150 feat(port): support customize running port (#188) 2019-03-22 17:47:49 +08:00
Minghe
d9e132e49b fix(cc): fix circleci config (#186) 2019-03-22 10:19:45 +08:00
Minghe
4366f5cbca fix(sytax): all assets are vendored (#185)
* fix(sytax): all assets are vendored

* chore(*): add more
2019-03-22 09:45:13 +08:00
Minghe
30133c534c fix(init): init before up (#183) 2019-03-21 23:54:27 +08:00
Minghe
77f7ee3092 chore(*): bump version to release rust support (#181) 2019-03-21 23:51:14 +08:00
Minghe
bff8fdaf95 chore(timeout): longer build timeout (#180)
* docs(readme): update readme

* feat(timeout): longer timeout
2019-03-21 23:49:18 +08:00
Minghe
14c5e841a9 feat(rust): support rust (#179)
* feat(rust): support rust now

* chore(test): test for rust

* fix(test): commit missing rust example func

* chore(*): only test cli before release
2019-03-21 23:32:45 +08:00
Minghe
05f755ed64 fix(typo): update readme (#178) 2019-03-21 16:55:44 +08:00
Minghe
0605ac2716 feat(up): should show the service endpoint when up done (#177) 2019-03-21 16:50:50 +08:00
Minghe
d54a4c23c8 fix(env): when no proxy created, should run one (#176)
* chore(git): update vendor

* fix(env): should run proxy when no proxy created
2019-03-21 16:50:32 +08:00
Minghe
778c718282 doc(readme): update readme (#175)
* doc(readme): update readme

* doc(wiki): remove wiki

* chore(*): bump version
2019-03-20 20:54:58 +08:00
Minghe
f04bbd2403 feat(refactor): * (#173)
* 1. user docker remote api instead of docker golang sdk to do stuff
2. remote gRPC code
3. simplify command

* fix(dep): remove private import

* chore(*): clean up

* chore(*): clean up

* chore(*): commit source

* fix(test): *

* fix(env): enable docker remote api

* fix(env): enable docker remote api

* chore(*): clean up

* fix(ci): use machine to do build

* fix(ci): use machine to do build

* fix(ci): use machine to do build

* fix(ci): use machine to do build

* fix(ci): use machine to do build

* fix(ci): use machine to do build

* fix(ci): use machine to do build

* fix(ci): use machine to do build

* fix(ci): use machine to do build

* fix(ci): use machine to do build

* fix(ci): use machine to do build

* fix(ci): use machine to do build

* fix(ci): use machine to do build

* fix(ci): use machine to do build

* feat(timeout): longger timeout

* fix(test): *

* fix(typo): flag is name

* chore(*): debug

* chore(*): debug

* chore(*): decrease test time

* fix(type): disable call test since not well design yet

* fix(typo): remove,

* feat(images): pull images

* fix(Pkg): using Pkg first

* fix(Pkg): using Pkg first

* feat(julia): fix version

* chore(*): clean up

* fix(file): ensure file exist

* feat(http): remote http test

* fix(circleci): fix deploy job

* chore(*): update info

* feat(init): update script

* doc(architect): update readme

* refactor(api): refactor api code

* refacot(api): seperate version

* refactor(build): service build as single file

* feat(concurrent): down concurrent

* refactor(api): refactor API

* fix(endpoint): valid endpoint

* fix(path): path change

* feat(release): fix release script

* fix(path): correct path

* feat(api): seperate service run

* fix(release): install goreleaser

* fix(cc): fix cc

* fix(releaser): install releaser from script outside of circleci config

* fix(env): init logic move env

* fix(cli): fix init

* fix(env): avoid conflict

* chore(*): update output

* test(stop): add test for stop

* feat(label):apply default label

* doc(readme): update workflow graph

* fix(init): should just start when container exist

* feat(state): update container by state
2019-03-20 17:06:52 +08:00
Minghe
21ec74b03b feat(architect): architecture refactor (#170)
* refactor(*): move service from api

* fix(import): fix paht

* chore(*): update vendor
2019-02-18 20:54:43 +08:00
FrontMage
1be99b5b25 Add rust base image for Rust (#169)
Add rust base image for Rust
2019-01-02 17:35:01 +08:00
Minghe Huang
cf7bf9e71c clean code and fix version issue 2018-08-03 17:49:00 +08:00
Minghe Huang
9d35b29ff5 clean code 2018-08-03 15:54:03 +08:00
Minghe Huang
56afefb143 fix typo 2018-08-03 00:59:00 +08:00
Minghe Huang
f208d7c8d2 fix test 2018-08-03 00:49:05 +08:00
Minghe Huang
3ac61fea2d bump version 2018-08-03 00:43:22 +08:00
Minghe
884fb65432 Remove path (#162)
* clean up

* remove Path

* fix typo

* add more test

* fix typo

* fix permission issue

* fix server not started issue

* clean up
2018-08-03 00:41:33 +08:00
Minghe
24f9b53e76 remove container after 'fx call' end (#161)
* call by grpc client

* add test

* clean code
2018-08-02 20:19:41 +08:00
Minghe
61e153b59a Merge branch 'production' into master 2018-07-28 15:44:18 +08:00
Minghe
3105fe1b5a Fix remote addr (#159)
* use remote url since fx call will call on a remote server

* bump version
2018-07-28 15:42:40 +08:00
Minghe
584e1a67fc Doc (#158)
* update doc and setup wiki

* update README

* update README
2018-07-27 17:34:13 +08:00
Minghe
cc3d3a8d9f deploy (#156)
* fix typo

* fix output issue on call

* bump version

* Add/call service (#154)

add '/call' endpoint

* Add/call service (#155)

* add call endpoint

* remove debug code

* add Call method to FxService

* bump version
2018-07-22 22:40:06 +08:00
Minghe
303c75e9cb Merge branch 'production' into master 2018-07-22 22:39:23 +08:00
Minghe Huang
e775331f23 bump version 2018-07-22 22:38:09 +08:00
Minghe
8dfc5b947f Add/call service (#155)
* add call endpoint

* remove debug code

* add Call method to FxService
2018-07-22 22:36:41 +08:00
Minghe
fb55abb6b5 Add/call service (#154)
add '/call' endpoint
2018-07-22 22:34:58 +08:00
Minghe
c338d28498 deploy (#153)
* fix typo

* fix output issue on call

* bump version
2018-07-16 23:47:02 +08:00
Minghe Huang
26ef3c6027 bump version 2018-07-16 23:46:28 +08:00
Minghe Huang
843df76eb1 fix output issue on call 2018-07-16 23:46:05 +08:00
Minghe Huang
71f95067f8 fix typo 2018-07-16 23:46:05 +08:00
Minghe
95d36fc1f0 deploy (#152)
* fix typo

* WIP: Call (#151)

* bump version

* init a docker image to support run script

* a docker to run different script langs

* -d on Linux platform

* improve usage message (#149)

* fix typo

* Add Call command

* workflow connected, but params parsing needed

* feat(*): support fx call now

* noneed change

* bump version
2018-07-16 22:58:04 +08:00
Minghe
dbf6ee77fc fix typo (#150) 2018-06-25 17:35:10 +08:00
Minghe
aa68702476 improve usage message (#149) 2018-06-25 17:14:56 +08:00
Minghe
b36b9979d8 bump version (#147) 2018-06-24 23:06:57 +08:00
Minghe
9ed073a4f6 fix use not working issue (#146) 2018-06-24 23:03:11 +08:00
Minghe
ab90fe4cde Release (#144)
* refactor config (#140) (#141)

* refactor config

* fix uri issue

* release (#142)

* refactor config (#140)

* refactor config

* fix uri issue

* bump version

* release 0.0.7
2018-06-24 20:54:52 +08:00
Minghe
55d0dbeca9 Status (#143) 2018-06-24 20:54:52 +08:00
Minghe
e22d371722 release (#142)
* refactor config (#140)

* refactor config

* fix uri issue

* bump version
2018-06-24 00:53:25 +08:00
Minghe
5b9685a5b5 refactor config (#140) (#141)
* refactor config

* fix uri issue
2018-06-24 00:40:22 +08:00
Minghe Huang
cd017b2e1e bump version 2018-06-23 19:56:26 +08:00
Minghe Huang
fef248849c bump version 2018-06-23 19:55:05 +08:00
Minghe Huang
50bdf6e31c bump version 2018-06-23 19:40:13 +08:00
Minghe
d495a1d7f1 Add use (#134) 2018-06-23 19:39:15 +08:00
Minghe Huang
850b186592 update README 2018-06-23 16:30:06 +08:00
Minghe
b0df98600e Clean code (#132) 2018-06-23 16:14:14 +08:00
Minghe Huang
d325753bb7 fix typo 2018-06-20 17:25:07 +08:00
Minghe Huang
7b4a6a37c8 Add version file 2018-06-20 17:07:17 +08:00
Minghe Huang
e51d6d86f8 Add release 2018-06-20 16:55:58 +08:00
Minghe Huang
d73afe8666 short commit id 2018-06-20 16:37:19 +08:00
Minghe
950c65d2c6 Deploy (#130)
* setup ci

* run all test

* fix build

* disable test

* remove build step since release step will do build

* add missing deps

* update version

* auto tag

* set name and email
2018-06-20 16:35:44 +08:00
Minghe Huang
56967bf689 fix test 2018-06-20 11:35:35 +08:00
Minghe
d66eadb710 Refactor flag parsing code (#129) 2018-06-20 10:50:02 +08:00
Minghe Huang
77a97c1689 fix(*): verbose undefined 2018-06-19 22:00:16 +08:00
Minghe
2d7af0ea27 add test (#128) 2018-06-19 21:55:16 +08:00
Minghe Huang
60efd92527 fix wrong task name issue 2018-06-19 16:25:56 +08:00
Minghe Huang
5b172708e8 update circleci config 2018-06-19 16:22:14 +08:00
Minghe Huang
ce88cacfb5 Fix go get met no Go file issue 2018-06-19 16:04:35 +08:00
Minghe Huang
aedba3ee7c add submode update step 2018-06-19 15:59:17 +08:00
Minghe Huang
a224c4add4 clean up 2018-06-19 15:57:33 +08:00
Minghe Huang
21a51d289c clean up 2018-06-19 15:56:07 +08:00
Minghe Huang
1f7c8ce5a2 clean up 2018-06-19 15:56:00 +08:00
Minghe Huang
1287ab8743 fix path issue 2018-06-19 15:43:46 +08:00
Minghe Huang
ed5ac21613 clean up 2018-06-17 01:29:24 +08:00
Minghe Huang
bdbc558470 clean up 2018-06-17 01:25:21 +08:00
Minghe Huang
fb39606933 clean code 2018-06-17 01:12:28 +08:00
Minghe
06bd14fb45 Refactor (#126) 2018-06-17 01:05:51 +08:00
Minghe
0df6eb71e0 circleci workflow 2018-06-15 23:48:23 +08:00
Minghe Huang
241e680302 add new contributor 2018-01-31 13:29:36 +08:00
Minghe Huang
7ada940f0a Merge branch 'master' of https://github.com/metrue/fx 2018-01-31 13:27:47 +08:00
Minghe
c156f68ea0 Merge pull request #123 from steventhanna/master
Added syntax highlighting for code snippets
2018-01-26 08:06:09 +08:00
Steven Hanna
5b93ecd834 Added syntax highlighting for code snippets
Added syntax highlighting for code snippets in the `README.md`
2018-01-25 11:06:39 -05:00
Minghe Huang
104a5705b9 update README 2018-01-21 20:51:45 +08:00
Minghe
1f5244e087 Merge pull request #122 from andre2007/master
Added D to list of supported languages
2018-01-21 11:34:23 +08:00
=
6b3cddf847 Added D to list of supported languages 2018-01-20 21:10:40 +01:00
Minghe Huang
c2750e776f update port 2018-01-13 13:44:52 +08:00
Minghe
173a4207a9 Merge pull request #120 from metrue/fix/monitor-base-image-pull
Fix/monitor base image pull
2018-01-07 16:12:29 +08:00
Minghe Huang
b62026c692 disable api/service coverage test 2018-01-07 16:05:11 +08:00
Minghe Huang
9d1c6f6b60 use make build 2018-01-07 15:54:54 +08:00
Minghe Huang
af2e67e301 refactor testing 2018-01-07 15:49:47 +08:00
Minghe Huang
8a2ba8172c enable test of api/service 2018-01-07 15:33:33 +08:00
Minghe Huang
e050770473 friendly message 2018-01-07 15:32:44 +08:00
Minghe Huang
1aebe626af use channel to monitor base image pull task 2018-01-07 15:27:32 +08:00
Minghe Huang
3c24781d36 temp disable api/service test to green the build 2018-01-07 12:18:58 +08:00
Minghe Huang
b57d7f79e9 friendly message when env is not ready 2018-01-06 17:38:56 +08:00
Minghe
dce74a9b57 Merge pull request #119 from metrue/improve/output
Improve/output
2018-01-06 16:58:48 +08:00
Minghe Huang
391c1a9fa8 use ASCII table lib to process output 2018-01-06 16:56:57 +08:00
Minghe Huang
7de6f7db9d use ASCII table lib to process output 2018-01-06 16:56:51 +08:00
Minghe Huang
24661a6fa5 longer waiting time to make sure server ready before testing up 2018-01-06 16:13:25 +08:00
Minghe
6d2c682d4b Merge pull request #118 from metrue/error-handler
use global error handler
2018-01-06 16:06:01 +08:00
Minghe Huang
db4a0026a2 use global error handler 2018-01-06 15:56:43 +08:00
Minghe Huang
9524de1e9e add development status section 2017-12-31 16:17:05 +08:00
Minghe
a0d69eb61f fix circleci failure 2017-12-21 04:59:11 +00:00
Minghe Huang
0e11e453dc fix warning since use array 2017-12-17 13:20:03 +08:00
Minghe
3ebcd2a857 Merge pull request #106 from muka/fixalldown
added back support for `fx down *`
2017-12-17 13:13:00 +08:00
Minghe
a8c60ad9f7 update the bin path also 2017-12-17 05:07:26 +00:00
Minghe
11a0d21c0d Merge pull request #111 from muka/fixgen
review install-deps and gen.sh to use local refs
2017-12-17 12:58:29 +08:00
Luca Capra
96e0403dad review install-deps and gen.sh to use local refs 2017-12-16 22:02:35 +01:00
Luca Capra
8bedb38eb9 Merge branch 'fixalldown' of github.com:muka/fx into fixalldown 2017-12-16 19:00:13 +01:00
Luca Capra
f386c007eb review formatter output 2017-12-16 18:58:28 +01:00
Luca Capra
d8c616b2d3 Merge branch 'master' of https://github.com/metrue/fx into fixalldown 2017-12-16 18:58:16 +01:00
Minghe Huang
5d57c5df51 fix typo 2017-12-17 01:44:53 +08:00
Minghe Huang
8d89e63b14 add more contributtors 2017-12-17 01:42:46 +08:00
Minghe Huang
ce290dcb3b fix wrong file name 2017-12-17 01:36:07 +08:00
Minghe Huang
cae4f3e3f7 fix wrong file name 2017-12-17 01:36:05 +08:00
Minghe Huang
1fc9ba1594 add .gitattribute 2017-12-17 01:33:59 +08:00
Minghe Huang
92f1ba2bf0 auto bundle asset into binary with go-bindata 2017-12-17 01:28:03 +08:00
Minghe
0fdebbd05b Merge branch 'master' into fixalldown 2017-12-17 01:13:18 +08:00
Luca Capra
63fa802e63 Merge branch 'master' into fixalldown 2017-12-16 18:08:46 +01:00
Minghe
70fd259ca6 Merge pull request #105 from andre2007/master
Initial D support
2017-12-17 01:06:39 +08:00
Minghe
37ace80123 add d language stuff 2017-12-16 17:02:11 +00:00
Minghe
3128421b6b fix some syntax issue 2017-12-17 00:39:48 +08:00
Minghe Huang
7c6a22461c add api/google into gitignore 2017-12-17 00:10:26 +08:00
=
3371549c0b Review comments 2017-12-16 16:50:43 +01:00
Luca Capra
7aad3c6319 review List handler to return running container only 2017-12-16 14:50:24 +01:00
Luca Capra
b8b1432ba3 apply * logic to down only 2017-12-16 13:10:42 +01:00
Luca Capra
ba3047b6f3 review start stop service in test 2017-12-16 10:21:20 +01:00
Luca Capra
e5c60c933c ign coverage.txt 2017-12-16 10:13:48 +01:00
Luca Capra
ef2bd66bb1 wait for service to start 2017-12-16 10:07:04 +01:00
Luca Capra
327dbc2251 review verbose for pull 2017-12-16 10:01:40 +01:00
Luca Capra
bce63388f2 added back support for 2017-12-16 08:02:29 +01:00
=
665ffae490 Merge remote-tracking branch 'upstream/master' 2017-12-15 20:40:55 +01:00
=
8df9cd658a Initial D support 2017-12-15 20:29:50 +01:00
Minghe Huang
5b233491f0 install googleapis which needed by api/ 2017-12-14 23:32:12 +08:00
Minghe Huang
599eeca2c2 clean code 2017-12-14 22:54:33 +08:00
Minghe
e660a64c36 Update README.md 2017-12-14 12:26:08 +08:00
Minghe
656a20b259 Rename NEW_LANGUAGE_SUPPORT to NEW_LANGUAGE_SUPPORT.md 2017-12-14 12:22:48 +08:00
Minghe
1862756282 Create NEW_LANGUAGE_SUPPORT 2017-12-14 12:22:30 +08:00
Minghe
15001efc39 Merge pull request #102 from metrue/provision-tools
WIP: add protoc installation script
2017-12-14 12:17:54 +08:00
Minghe Huang
e62adc99fa download and install protoc locally 2017-12-14 02:51:58 +00:00
Minghe Huang
5c8be67a57 add protoc installation script 2017-12-13 23:25:27 +08:00
Minghe
7eb6124dad Merge pull request #100 from muka/grpc
Use gRPC over websocket
2017-12-13 22:40:15 +08:00
Luca Capra
3c57e130b9 merge master 2017-12-13 06:41:29 +01:00
Minghe Huang
0b93e7379b update .gitignore 2017-12-13 13:27:58 +08:00
Luca Capra
2396fec147 avoid duplicate header in coverage output 2017-12-12 21:35:24 +01:00
Luca Capra
744308cf5b added protoc setup example 2017-12-12 21:16:44 +01:00
Luca Capra
747273dad5 use same package to have correct coverage assesment 2017-12-12 21:04:56 +01:00
Luca Capra
68b630aaeb add comments to address codecov checks 2017-12-12 20:21:32 +01:00
Luca Capra
4afbdbc83c remove variable from test command 2017-12-12 20:06:43 +01:00
Luca Capra
b1b2ae5a15 refactor with tests 2017-12-12 08:06:57 +01:00
Luca Capra
f816bd9539 Merge branch 'grpc' of github.com:muka/fx into grpc 2017-12-12 06:54:41 +01:00
Luca Capra
4a81e90469 handle errors concurrently 2017-12-12 06:54:30 +01:00
lcapra
9025464369 remove dangling message reference 2017-12-11 12:13:25 +01:00
lcapra
3317b936e3 fix context reference 2017-12-11 12:10:46 +01:00
lcapra
98c1f65b66 ensure dep 2017-12-11 11:59:57 +01:00
lcapra
a556e50d11 fix dep name 2017-12-11 11:58:29 +01:00
lcapra
d02ed1d748 review dep requirements 2017-12-11 11:57:00 +01:00
Luca Capra
976deaad53 handle errors explicitly 2017-12-11 07:15:32 +01:00
Luca Capra
21ea85f33a service test 2017-12-11 06:51:00 +01:00
Luca Capra
484455d850 fix pointers 2017-12-10 16:18:58 +01:00
Luca Capra
f911d34767 avoid struct transformation 2017-12-10 16:15:56 +01:00
Luca Capra
ed4d1c87d8 remove redundant struct 2017-12-10 16:13:26 +01:00
Luca Capra
cebcfaaffd remove redundant structs in message 2017-12-10 16:11:24 +01:00
Luca Capra
4c70089cde refactor api -> api/service 2017-12-10 16:06:31 +01:00
Luca Capra
d1ff152bfe Merge branch 'master' of https://github.com/metrue/fx 2017-12-10 15:38:57 +01:00
Luca Capra
202ed7d1df initial client-server integration 2017-12-10 12:53:45 +01:00
Luca Capra
2219c3f1c9 refactor commands to use grpc 2017-12-10 12:17:21 +01:00
Luca Capra
2616229307 refactor to use grp exposed service as default 2017-12-10 11:35:57 +01:00
Minghe
05a0372672 Merge pull request #99 from metrue/develop
Develop
2017-12-10 18:28:18 +08:00
Minghe Huang
501965fffc Add coverage badge 2017-12-10 18:27:37 +08:00
Minghe Huang
174607546f add coverage 2017-12-10 18:24:33 +08:00
Minghe Huang
599966aea5 clean up after test run 2017-12-10 18:04:28 +08:00
Luca Capra
6dba9a4ef2 added initial gRPC service 2017-12-10 10:12:19 +01:00
Luca Capra
3cc9694c69 rename package api to docker 2017-12-10 09:30:19 +01:00
Minghe
e53edb20cf Merge pull request #97 from metrue/develop
should check environment if ok
2017-12-09 16:34:31 +08:00
Minghe Huang
dcf2d1e38f should check environment if ok 2017-12-09 13:58:12 +08:00
Minghe Huang
727963bb14 update README 2017-12-09 11:15:56 +08:00
Minghe Huang
b13ac2943b update README 2017-12-09 11:10:58 +08:00
Minghe
4e2a5ff260 Merge pull request #95 from metrue/develop
Develop
2017-12-09 11:08:55 +08:00
Minghe Huang
b77e8a6cd1 upgrade 2017-12-09 02:58:32 +00:00
Minghe Huang
ed082eea49 clean up 2017-12-09 10:53:52 +08:00
Minghe Huang
e92a2ca4a0 update README 2017-12-09 10:53:21 +08:00
Minghe Huang
612d83c8e2 Merge branch 'develop' 2017-12-09 10:36:53 +08:00
Minghe Huang
7ee48f56b2 install.sh works now 2017-12-09 02:14:09 +00:00
Minghe Huang
84b8778ddf add install script 2017-12-09 09:47:31 +08:00
Minghe
db739c1209 Merge pull request #93 from metrue/develop
Develop
2017-12-09 09:04:00 +08:00
Minghe Huang
a0e9bae89b excape - 2017-12-09 08:57:23 +08:00
Minghe Huang
317f00ea5b add unit test 2017-12-09 08:53:34 +08:00
Minghe Huang
c93eada317 fix test 2017-12-09 08:49:28 +08:00
Minghe Huang
384c192c04 format up message 2017-12-09 01:33:37 +08:00
Minghe Huang
e72e0d5efa refractor up 2017-12-09 01:25:09 +08:00
Minghe Huang
3735ec2260 format down result message 2017-12-09 00:06:53 +08:00
Minghe Huang
8bf60ff016 fx no depend on zsh and git 2017-12-08 22:24:30 +08:00
Minghe Huang
cefcd77192 trying format message 2017-12-08 22:00:53 +08:00
Minghe Huang
b95db62561 update 2017-12-08 07:09:44 +00:00
Minghe
2872f64a12 Merge pull request #91 from xwjdsh/master
Optimizing code
2017-12-08 14:41:39 +08:00
Wendell Sun
07845db5ae Optimizing code 2017-12-08 12:41:06 +08:00
Minghe
2c450fa549 Merge pull request #90 from metrue/develop
Refine dir/module
2017-12-08 12:13:42 +08:00
Minghe Huang
93ee7d868e Refine dir/module 2017-12-08 12:08:43 +08:00
Minghe
775afd0d2b Merge pull request #89 from metrue/remove-download-images
Remove download images
2017-12-08 12:01:12 +08:00
Minghe Huang
27a3dc92fb fix Java build 2017-12-08 11:53:30 +08:00
Minghe Huang
18ee51ff07 java is use Uppercase for public class 2017-12-08 11:47:35 +08:00
Minghe Huang
dfb372c42f no need to download the preset image from github 2017-12-08 11:35:16 +08:00
Minghe Huang
06a79c3fa1 Clean up 2017-12-08 11:28:39 +08:00
Minghe Huang
e50fd6b799 fix typo 2017-12-08 11:26:54 +08:00
Minghe Huang
8ec1d29cec no need to use old image preparing step anymore 2017-12-08 11:22:37 +08:00
Minghe Huang
768232d625 the first TDD golang in 2017-12-08 10:57:16 +08:00
Minghe Huang
599e9a596f fix test a little 2017-12-08 10:45:40 +08:00
Minghe Huang
e31f6605dd fix some test issue 2017-12-08 10:08:03 +08:00
Minghe Huang
09ced6210d Merge branch 'remove-download-images' of https://github.com/metrue/fx into remove-download-images 2017-12-07 17:37:10 +08:00
Minghe Huang
c077cb55d5 add image module 2017-12-07 17:31:12 +08:00
Minghe Huang
2f96dfefec update since dir refined 2017-12-07 11:02:15 +08:00
Minghe Huang
61113c5404 refine dir 2017-12-07 10:52:46 +08:00
Minghe Huang
1c56ae5037 clean up 2017-12-07 10:14:39 +08:00
Minghe Huang
998be24c84 prof go-bindata works 2017-12-07 09:58:10 +08:00
Minghe Huang
c2d8545e15 add asset module 2017-12-06 18:21:04 +08:00
Minghe Huang
10df127f55 yes, go-binddata works 2017-12-06 06:43:28 +00:00
Minghe Huang
f7ed3cc681 use go-bindata to include file stuff 2017-12-05 01:52:17 +00:00
Minghe
27a02c8a74 Merge pull request #82 from metrue/develop
add verbose option to fx serve
2017-12-04 23:45:13 +08:00
Minghe Huang
225e8723ba add verbose option to fx serve 2017-12-04 23:40:21 +08:00
Minghe
e50e144346 Merge pull request #81 from metrue/develop
clean up
2017-12-04 20:44:58 +08:00
Minghe Huang
a836b9c9c9 clean up 2017-12-04 20:39:59 +08:00
Minghe Huang
61b82d28b6 Clean up 2017-12-04 20:38:51 +08:00
Minghe
e7b5d3f745 Merge pull request #77 from xwjdsh/master
Remove build image when executing fx down
2017-12-04 20:11:32 +08:00
Wendell Sun
d5fae747f7 Remove build image when executing fx down 2017-12-04 17:49:37 +08:00
Minghe Huang
62379a410f fix deps stuff 2017-12-04 04:28:32 +00:00
Minghe
8ed8fac9e9 Merge pull request #76 from metrue/add-code-of-conduct-1
Create CODE_OF_CONDUCT.md
2017-12-04 12:20:07 +08:00
Minghe
fe54495f4d Create CODE_OF_CONDUCT.md 2017-12-04 12:19:48 +08:00
Minghe Huang
d945634de4 add @xwjdsh to contributors list 2017-12-04 12:14:19 +08:00
Minghe
fb2c8d109b Merge pull request #75 from xwjdsh/master
Shows all-state container and display state column
2017-12-04 12:09:11 +08:00
Wendell Sun
59053bf626 Shows all-state container and display state column 2017-12-04 11:45:46 +08:00
Minghe
3fa4d1cbb6 Merge pull request #74 from metrue/develop
Develop
2017-12-04 10:29:10 +08:00
Minghe
6c3af11fd9 Merge pull request #72 from metrue/refactor-up
Refactor up
2017-12-04 09:59:51 +08:00
Minghe Huang
9f18f5f315 should use path.Join to combine path 2017-12-04 09:38:44 +08:00
Minghe
29a0745aea Merge pull request #69 from xwjdsh/master
Remove container when execute fx down
2017-12-04 09:32:24 +08:00
Minghe
30a60d3ade Merge pull request #70 from xwjdsh/fix-40
Cleanup temp file when build image was done
2017-12-04 09:31:33 +08:00
Minghe
ed5d57a32f Merge pull request #71 from xwjdsh/list-fx-only
Set fx label when building images and filter by it after
2017-12-04 09:30:35 +08:00
Wendell Sun
b78012485f Set fx label when building images and filter by it after 2017-12-04 01:55:17 +08:00
Wendell Sun
0ef5debd91 Invoke cleanup with defer 2017-12-04 01:00:42 +08:00
Wendell Sun
f3a2e99c24 Cleanup temp file when build image was done 2017-12-04 00:09:23 +08:00
Wendell Sun
8742f1c23d Remove container when execute fx down 2017-12-03 23:06:38 +08:00
Minghe
149006ee79 Merge pull request #68 from xwjdsh/master
Fix print error
2017-12-03 22:20:21 +08:00
Wendell Sun
bf28762e0d Fix print error 2017-12-03 21:25:17 +08:00
Minghe Huang
12822414f8 move get language from file name ext to utils 2017-12-03 18:44:44 +08:00
Minghe Huang
16a0538c6d refactor worker 2017-12-03 18:15:21 +08:00
Minghe Huang
549a0f2896 use FunctionMeta struct 2017-12-03 13:02:09 +08:00
Minghe Huang
88d91d630b fix typo 2017-12-02 14:23:27 +00:00
Minghe Huang
66e906ce96 update circleci config 2017-12-02 22:16:12 +08:00
Minghe Huang
57bfd50c85 then install 2017-12-02 22:12:10 +08:00
Minghe Huang
4bd92a88d1 use workable commit 2017-12-02 22:01:36 +08:00
Minghe Huang
50b37a72bd use * 2017-12-02 21:51:28 +08:00
Minghe Huang
fb2d1e14ee always up-to-date 2017-12-02 21:45:43 +08:00
Minghe Huang
f918878f6a updated deps 2017-12-02 13:33:43 +00:00
Minghe Huang
5d8bcac543 Refractor a little 2017-12-02 21:25:07 +08:00
Minghe Huang
da6b5795ee async pull image task 2017-12-02 21:11:27 +08:00
Minghe Huang
8c7a5bf6e4 fix typo 2017-12-02 18:09:09 +08:00
Minghe
9d8df70e80 Merge pull request #66 from metrue/fix/faster-deployment
Fix/faster deployment
2017-12-01 23:56:48 +08:00
Minghe Huang
f1655d81cb auto pull base image when serve start 2017-12-01 23:55:21 +08:00
Minghe Huang
6b26c46e23 add missing 2017-12-01 16:47:19 +08:00
Minghe Huang
23932e1ded pull image when init env 2017-12-01 16:44:31 +08:00
Minghe Huang
20b2fadf14 new release 2017-12-01 12:22:56 +08:00
Minghe Huang
e9c39b4703 clean up 2017-12-01 12:22:11 +08:00
Minghe
a80d98e6c0 Merge pull request #65 from metrue/dockerfile-refactor
Dockerfile refactor
2017-12-01 11:54:45 +08:00
Minghe Huang
f11b06e6d9 refactor java base image 2017-12-01 11:05:22 +08:00
Minghe Huang
e81032bd46 refactor to python base image 2017-12-01 09:26:53 +08:00
Minghe Huang
b8620b71af refractor some jenkinsfile 2017-12-01 00:14:55 +08:00
Minghe Huang
f066e841e8 Refactor node base image to base dockerfile 2017-12-01 00:06:46 +08:00
Minghe Huang
4bb67a9514 refractor Dockerfile base to base image 2017-11-30 23:47:19 +08:00
Minghe Huang
bef5250cfb add java test 2017-11-30 14:18:33 +08:00
Minghe Huang
e50ddaf004 fix typo 2017-11-30 10:36:42 +08:00
Minghe Huang
a45151c8e5 add zip images command 2017-11-30 10:29:53 +08:00
Minghe Huang
2313d41e6c fix wrong zip issue 2017-11-30 10:27:37 +08:00
Minghe Huang
5390e74365 Add example function for java 2017-11-30 10:24:08 +08:00
Minghe Huang
c9793cda30 release java support 2017-11-30 10:20:36 +08:00
Minghe Huang
0840644f69 fix case issue in file name 2017-11-30 02:16:39 +00:00
Minghe Huang
315ff33cf7 add missing file 2017-11-30 10:11:26 +08:00
Minghe Huang
268d308e1b upodate READEME 2017-11-30 10:06:26 +08:00
Minghe Huang
bcf6dbd1a4 support java 2017-11-30 09:55:33 +08:00
Minghe
34df47d010 Merge pull request #64 from chlins/master
Fix unclosed channel
2017-11-29 17:46:46 +08:00
chlins
4dc7cc17c3 Fix unclosed channel 2017-11-29 17:19:01 +08:00
Minghe Huang
1ef791cd6e java support basically proved 2017-11-29 16:46:24 +08:00
Minghe Huang
768be125cd clean code 2017-11-29 16:23:39 +08:00
Minghe Huang
5816870074 naming 2017-11-29 16:21:54 +08:00
Minghe Huang
fa191b35b8 java basically work 2017-11-29 16:17:34 +08:00
Minghe Huang
d961614d79 update README 2017-11-26 00:15:37 +08:00
Minghe Huang
1ccd323d1c fix typo 2017-11-25 19:30:26 +08:00
Minghe
2b1bd16510 Merge pull request #63 from chlins/master
Fix a bug
2017-11-25 16:20:24 +08:00
chlins
ca6493527e Fix a bug 2017-11-25 15:54:00 +08:00
Minghe
88adb68bb4 Merge pull request #62 from chlins/master
Move logger to outer
2017-11-25 14:59:37 +08:00
chlins
dd90aa09c1 Move logger to outer 2017-11-25 14:07:42 +08:00
Chenyu Zhang
81a58223c5 Merge pull request #3 from metrue/master
Merge
2017-11-22 16:36:52 +08:00
Chenyu Zhang
dfa8adf3ac Merge pull request #2 from metrue/master
update
2017-11-20 09:34:03 +08:00
792 changed files with 14190 additions and 70041 deletions

View File

@@ -1,55 +1,73 @@
defaults: &defaults
machine: true
environment:
IMPORT_PATH: "github.com/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME"
OUTPUT_DIR: "./build"
DIST_DIR: "./dist"
install_golang: &install_golang
run:
name: install Golang 1.11
command: |
sudo add-apt-repository ppa:gophers/archive
sudo apt-get update
sudo apt-get install golang-1.11-go
alias go="/usr/lib/go-1.11/bin/go"
go version
install_deps: &install_deps
run:
name: Install deps
command: |
/usr/lib/go-1.11/bin/go mod vendor
/usr/lib/go-1.11/bin/go get -u github.com/gobuffalo/packr/packr
install_httpie: &install_httpie
run:
name: install httpie
command: |
sudo apt-get -y update && sudo apt-get -y install httpie
install_jq: &install_jq
run:
name: install jq
command: |
sudo apt-get update && sudo apt-get -y install jq
build_binary: &build_binary
run:
name: build binary
command: |
/usr/lib/go-1.11/bin/go build -o ${OUTPUT_DIR}/fx fx.go
unit_test: &unit_test
run:
name: unit test
command: |
make unit-test
bash <(curl -s https://codecov.io/bash) -t ${CODECOV_TOKEN}
cli_test: &cli_test
run:
name: cli test
command: make cli-test
version: 2
machine:
services:
- docker
dependencies:
override:
- sudo add-apt-repository ppa:masterminds/glide -y
- sudo apt-get update
- sudo apt-get install glide -y
jobs:
build:
docker:
- image: circleci/golang:1.8
working_directory: /go/src/github.com/metrue/fx
test:
<<: *defaults
steps:
- checkout
- setup_remote_docker
- *install_golang
- *install_deps
- *unit_test
- *build_binary
- run:
name: Install tools
command: |
go get github.com/golang/dep
cd $GOPATH/src/github.com/golang/dep
go install ./...
name: Pull images
command: make pull
- *cli_test
- run:
name: Build and Install
command: |
dep ensure
go install ./
- run:
name: Test
command: |
fx serve > server_output.log 2>&1 &
sleep 20
touch deploy.log
fx up examples/functions/func.js >> deploy.log
fx up examples/functions/func.rb >> deploy.log
fx up examples/functions/func.py >> deploy.log
fx up examples/functions/func.go >> deploy.log
fx up examples/functions/func.php >> deploy.log
fx up examples/functions/func.jl >> deploy.log
cat server_output.log
cat deploy.log;
cat deploy.log | grep 'Succed: 1' | wc -l | grep 6
deployment:
production:
branch: master
commands:
- echo "Not Ready Yet"
workflows:
version: 2
workflow:
jobs:
- test

View File

@@ -1,37 +0,0 @@
version: 2
dependencies:
override:
- sudo add-apt-repository ppa:masterminds/glide -y
- sudo apt-get update
- sudo apt-get install glide -y
jobs:
build:
docker:
- image: circleci/golang:1.8
working_directory: /go/src/github.com/metrue/fx
steps:
- checkout
- run:
name: Install tools
command: |
wget "https://github.com/Masterminds/glide/releases/download/0.10.2/glide-0.10.2-linux-amd64.tar.gz"
mkdir -p $HOME/bin
tar -vxz -C $HOME/bin --strip=1 -f glide-0.10.2-linux-amd64.tar.gz
export PATH="$HOME/bin:$PATH"
- run:
name: Build client
command: |
export PATH="$HOME/bin:$PATH"
cd client && make install-deps && make clean && make build
- run:
name: Build server
command: |
export PATH="$HOME/bin:$PATH"
cd server && make install-deps && make clean && make build
deployment:
production:
branch: master
commands:
- echo "Not Ready Yet"

5
.gitattributes vendored Normal file
View File

@@ -0,0 +1,5 @@
assets/**/* linguist-vendored
api/assets/**/* linguist-vendored
examples/**/* linguist-vendored
packer/images/**/* linguist-vendored
*.md linguist-documentation

1
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1 @@
ko_fi: metrue

9
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,9 @@
Issue: <url to the issue to fix>
Summary: <a brief summary of PR purpose>
The checklist before PR is ready for review:
- [ ] has unit testing for new added codes
- [ ] has functional testing for new added features
- [ ] has checked the lint or style issues
- [ ] README updated if need

102
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,102 @@
on: [push, pull_request]
name: ci
jobs:
Test:
runs-on: ubuntu-latest
steps:
- name: setup Go 1.12
uses: actions/setup-go@v1
with:
go-version: 1.12
id: go
- name: check out
uses: actions/checkout@master
- name: setup docker
run: |
./scripts/provision.sh
- name: setup k8s and kind
run: |
export GOBIN=$(go env GOPATH)/bin
export PATH=$PATH:$GOBIN
mkdir -p $GOBIN
curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
chmod +x kubectl && mv kubectl $GOBIN
wget https://github.com/kubernetes-sigs/kind/releases/download/v0.5.0/kind-linux-amd64 && chmod +x kind-linux-amd64 && mv kind-linux-amd64 $GOBIN/kind
./scripts/setup_kind.sh
- name: unit test
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
run: |
export KUBECONFIG=/home/runner/.kube/kind-config-fx-test
DEBUG=true go test -v ./container_runtimes/... ./deploy/...
- name: build fx
run: |
make build
- name: test fx-docker
run: |
cd ./contrib/docker_packer
make linux-build
make docker-build
make test
# make docker-publish #TODO in release workflow
- name: lint
run: |
export GOBIN=$(go env GOPATH)/bin
export PATH=$PATH:$GOBIN
go get -u github.com/golangci/golangci-lint/cmd/golangci-lint
golangci-lint run
- name: test fx cli
run: |
echo $KUBECONFIG
unset KUBECONFIG
make cli-test
- name: test AKS
env:
AKS_KUBECONFIG: ${{ secrets.AKS_KUBECONFIG }}
run: |
export KUBECONFIG=${HOME}/.kube/aks
echo ${AKS_KUBECONFIG} | base64 -d > $KUBECONFIG
if [[ -z "$AKS_KUBECONFIG" ]];then
echo "skip deploy test since no valid KUBECONFIG"
else
DEBUG=true ./build/fx deploy -n hello -p 12345 examples/functions/JavaScript/func.js
./build/fx destroy hello
rm ${KUBECONFIG}
fi
Installation:
runs-on: ${{ matrix.os }}
needs: [Test]
strategy:
fail-fast: true
matrix:
os:
- ubuntu-latest
# TODO enable window and mac
# - macOS-latest
# - windows-latest
version:
- latest
- v0.117.0
steps:
- name: Checkout
uses: actions/checkout@v1
- name: install fx
run: |
# install with non-root user
bash ./scripts/install.sh
./fx -v
# install with root
sudo bash ./scripts/install.sh
./fx -v

57
.github/workflows/docker.yml vendored Normal file
View File

@@ -0,0 +1,57 @@
on:
schedule:
- cron: '0 12 * * *'
name: docker
jobs:
Docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: login
uses: actions/docker/login@8cdf801b322af5f369e00d85e9cf3a7122f49108
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
- name: build-fx-go-image
uses: actions/docker/cli@master
with:
args: build -t metrue/fx-go-base:latest -f api/asserts/dockerfiles/base/go/Dockerfile
api/asserts/dockerfiles/base/go
- name: push-fx-go-image
uses: actions/docker/cli@master
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
with:
args: push metrue/fx-go-base:latest
- name: build-fx-rust-image
uses: actions/docker/cli@master
with:
args: build -t metrue/fx-rust-base:latest -f api/asserts/dockerfiles/base/rust/Dockerfile
api/asserts/dockerfiles/base/rust
- name: push-fx-rust-image
uses: actions/docker/cli@master
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
with:
args: push metrue/fx-rust-base:latest
- name: build-fx-node-image
uses: actions/docker/cli@master
with:
args: build -t metrue/fx-node-base:latest -f api/asserts/dockerfiles/base/node/Dockerfile
api/asserts/dockerfiles/base/node
- name: push-fx-node-image
uses: actions/docker/cli@master
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
with:
args: push metrue/fx-node-base:latest

117
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,117 @@
on:
push:
branches:
- '*--auto-release'
- master
- production
name: release
jobs:
Test:
runs-on: ubuntu-latest
steps:
- name: setup Go 1.12
uses: actions/setup-go@v1
with:
go-version: 1.12
id: go
- name: check out
uses: actions/checkout@master
- name: setup docker
run: |
./scripts/provision.sh
- name: setup k8s and kind
run: |
export GOBIN=$(go env GOPATH)/bin
export PATH=$PATH:$GOBIN
mkdir -p $GOBIN
curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
chmod +x kubectl && mv kubectl $GOBIN
wget https://github.com/kubernetes-sigs/kind/releases/download/v0.5.0/kind-linux-amd64 && chmod +x kind-linux-amd64 && mv kind-linux-amd64 $GOBIN/kind
./scripts/setup_kind.sh
- name: unit test
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
run: |
export KUBECONFIG=/home/runner/.kube/kind-config-fx-test
DEBUG=true go test -v ./container_runtimes/... ./deploy/...
- name: build fx
run: |
make build
- name: lint
run: |
export GOBIN=$(go env GOPATH)/bin
export PATH=$PATH:$GOBIN
go get -u github.com/golangci/golangci-lint/cmd/golangci-lint
golangci-lint run
- name: test fx cli
run: |
echo $KUBECONFIG
unset KUBECONFIG
make cli-test
- name: test AKS
env:
AKS_KUBECONFIG: ${{ secrets.AKS_KUBECONFIG }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
run: |
export KUBECONFIG=${HOME}/.kube/aks
echo ${AKS_KUBECONFIG} | base64 -d > $KUBECONFIG
DEBUG=true ./build/fx deploy -n hello -p 12345 examples/functions/JavaScript/func.js
./build/fx destroy hello
rm ${KUBECONFIG}
Release:
runs-on: ${{ matrix.os }}
needs: [Test]
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
# - macOS-latest
# - windows-latest
version:
- latest
# - v0.117.0
steps:
- name: setup Go
uses: actions/setup-go@v1
with:
go-version: '1.12'
- name: checkout
uses: actions/checkout@v1
- name: release
env:
GITHUB_TOKEN: ${{ secrets.GORELEASER_GITHUB_TOKEN }}
run: |
git config --global user.email "h.minghe@gmail.com"
git config --global user.name "Minghe Huang"
commit=$(git rev-parse --short HEAD)
version=$(cat fx.go| grep 'const version' | awk -F'"' '{print $2}')
echo "workflow is running on branch ${GITHUB_REF}"
if [[ ${GITHUB_REF} == "refs/heads/master" ]];then
version=${version}-alpha.${commit}
echo "alpha release $version"
elif [[ "${GITHUB_REF}" == *--auto-release ]];then
version=${version}-alpha.${commit}
echo "alpha release $version"
elif [[ ${GITHUB_REF} == "refs/heads/production" ]];then
echo "official release $version"
else
echo "skip release on $GITHUB_REF"
exit 0
fi
git tag -a ${version} -m "auto release"
curl -sL https://git.io/goreleaser | bash -s -- --skip-validate

8
.gitignore vendored
View File

@@ -3,4 +3,10 @@ vendor/
dist/
build/
*.pyc
fx
*.swp
/fx
/tmp
/api/google
/api/fx.pb.gw.go
/api/fx.pb.go
/coverage.txt

30
.golangci.yml Normal file
View File

@@ -0,0 +1,30 @@
run:
deadline: 10m
timeout: 10m
issues-exit-code: 1
tests: true
skip-dirs:
- examples
- api/images
- test/functions
linters:
enable:
- goimports
- stylecheck
- gosec
- interfacer
- unconvert
- goconst
- gocyclo
- misspell
- unparam
issues:
exclude-rules:
- path: _test\.go
linters:
- gocyclo
- goconst
- errcheck
- dupl
- gosec

View File

@@ -1,3 +1,6 @@
---
env:
- GO111MODULE=on
builds:
- main: fx.go
binary: fx
@@ -8,26 +11,24 @@ builds:
goarch:
- amd64
# Archive customization
archive:
format: tar.gz
replacements:
amd64: 64-bit
darwin: macOS
linux: Tux
files:
- README.md
brew:
github:
owner: metrue
name: homebrew-fx
commit_author:
name: metrue
email: h.minghe@gmail.com
folder: Formula
caveats: ""
homepage: "https://github.com/metrue/fx"
description: "fx, a simple but powerful Function as a Service build tools"
dependencies:
- git
- zsh
archives:
-
format: tar.gz
replacements:
amd64: 64-bit
darwin: macOS
linux: Tux
files:
- README.md
brews:
-
github:
owner: metrue
name: homebrew-fx
commit_author:
name: metrue
email: h.minghe@gmail.com
folder: Formula
caveats: ""
homepage: "https://github.com/metrue/fx"
description: "fx, a simple but powerful Function as a Service build tools"

46
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at H.Minghe@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

81
Gopkg.lock generated
View File

@@ -1,81 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
name = "github.com/Microsoft/go-winio"
packages = ["."]
revision = "78439966b38d69bf38227fbf57ac8a6fee70f69a"
version = "v0.4.5"
[[projects]]
name = "github.com/docker/distribution"
packages = ["digest","reference"]
revision = "48294d928ced5dd9b378f7fd7c6f5da3ff3f2c89"
version = "v2.6.2"
[[projects]]
name = "github.com/docker/docker"
packages = ["api/types","api/types/blkiodev","api/types/container","api/types/events","api/types/filters","api/types/mount","api/types/network","api/types/reference","api/types/registry","api/types/strslice","api/types/swarm","api/types/time","api/types/versions","api/types/volume","client","pkg/tlsconfig"]
revision = "092cba3727bb9b4a2f0e922cd6c0f93ea270e363"
version = "v1.13.1"
[[projects]]
name = "github.com/docker/go-connections"
packages = ["nat","sockets","tlsconfig"]
revision = "3ede32e2033de7505e6500d6c868c2b9ed9f169d"
version = "v0.3.0"
[[projects]]
name = "github.com/docker/go-units"
packages = ["."]
revision = "0dadbb0345b35ec7ef35e228dabb8de89a65bf52"
version = "v0.3.2"
[[projects]]
name = "github.com/gorilla/websocket"
packages = ["."]
revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b"
version = "v1.2.0"
[[projects]]
branch = "master"
name = "github.com/jhoonb/archivex"
packages = ["."]
revision = "be4efa7ec0c38ab76d56037014c90d48d6b13037"
[[projects]]
name = "github.com/phayes/freeport"
packages = ["."]
revision = "b8543db493a5ed890c5499e935e2cad7504f3a04"
version = "1.0.2"
[[projects]]
name = "github.com/pkg/errors"
packages = ["."]
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
version = "v0.8.0"
[[projects]]
name = "github.com/rs/xid"
packages = ["."]
revision = "02dd45c33376f85d1064355dc790dcc4850596b1"
version = "v1.1"
[[projects]]
branch = "master"
name = "golang.org/x/net"
packages = ["context","context/ctxhttp","proxy"]
revision = "9dfe39835686865bff950a07b394c12a98ddc811"
[[projects]]
branch = "master"
name = "golang.org/x/sys"
packages = ["windows"]
revision = "0ac51a24ef1c37380f98ba8b98f56e3bffd59850"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "f39bdc99a6e57f902cb0bbb772098222008d68464eac29614370e04d9080c8b0"
solver-name = "gps-cdcl"
solver-version = 1

View File

@@ -1,43 +0,0 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
[[constraint]]
name = "github.com/docker/docker"
[[constraint]]
name = "github.com/docker/go-connections"
[[constraint]]
name = "github.com/gorilla/websocket"
[[constraint]]
name = "github.com/jhoonb/archivex"
[[constraint]]
name = "github.com/metrue/fx"
[[constraint]]
name = "github.com/phayes/freeport"
[[constraint]]
name = "github.com/rs/xid"

View File

@@ -1,15 +1,34 @@
OUTPUT_DIR=./build
DIST_DIR=./dist
install-deps:
@dep ensure
lint:
golangci-lint run
generate:
packr
build:
go build -o ${OUTPUT_DIR}/fx fx.go
cross:
pull:
./scripts/pull.sh
cross: generate
goreleaser --snapshot --skip-publish --skip-validate
release:
goreleaser --skip-validate
clean:
rm -rf ${OUTPUT_DIR}
rm -rf ${DIST_DIR}
.PHONY: test build start list clean
unit-test:
./scripts/coverage.sh
cli-test:
./scripts/test_cli.sh
http-test:
./scripts/http_test.sh
zip:
zip -r images.zip images/
.PHONY: test build start list clean generate

358
README.md
View File

@@ -1,150 +1,300 @@
fx
------
Poor man's function as a service.
<br/>
![ci](https://github.com/metrue/fx/workflows/ci/badge.svg)
![build](https://circleci.com/gh/metrue/fx.svg?style=svg&circle-token=bd62abac47802f8504faa4cf8db43e4f117e7cd7)
[![codecov](https://codecov.io/gh/metrue/fx/branch/master/graph/badge.svg)](https://codecov.io/gh/metrue/fx)
[![Go Report Card](https://goreportcard.com/badge/github.com/metrue/fx?style=flat-square)](https://goreportcard.com/report/github.com/metrue/fx)
[![Go Doc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](http://godoc.org/github.com/metrue/fx)
![](https://img.shields.io/github/license/metrue/fx.svg)
[![Release](https://img.shields.io/github/release/metrue/fx.svg?style=flat-square)](https://github.com/metrue/fx/releases/latest)
### Introduction
## Table of Contents
- [Introduction](#introduction)
- [Installation](#installation)
- [Usage](#usage)
- [Contribute](#contribute)
## Introduction
fx is a tool to help you do Function as a Service on your own server. fx can make your stateless function a service in seconds. The most exciting thing is that you can write your functions with most programming languages.
| Language | Status | Contributor |
| ------------- |:-------------:|:-------------:|
| Go | Supported | fx |
| Node | Supported | fx |
| Python | Supported | fx |
| Ruby | Supported | fx |
| PHP | Supported | [@chlins](https://github.com/chlins)|
| Julia | Supported | [@mbesancon](https://github.com/mbesancon)|
| Java | No | |
| Scala | No | |
| Perl | Working on | |
| .Net | Working on | |
| R | Working on | |
| Rust | Working on | |
Feel free hacking fx to support the languages not listed. Welcome to tweet me [@_metrue](https://twitter.com/_metrue) on Twitter, [@metrue](https://www.weibo.com/u/2165714507) on Weibo.
tweet [@_metrue](https://twitter.com/_metrue) or issue is welcome.
### Usage
| Language | Status | Contributor | Example |
| ------------- |:-------------:|:-------------:| :-------------:|
| Go | Supported | fx | [/examples/Golang](https://github.com/metrue/fx/tree/master/examples/functions/Golang) |
| Rust | Supported | [@FrontMage](https://github.com/FrontMage)| [/examples/Rust](https://github.com/metrue/fx/tree/master/examples/functions/Rust) |
| Node | Supported | fx | [/examples/JavaScript](https://github.com/metrue/fx/tree/master/examples/functions/JavaScript) |
| Python | Supported | fx | [/examples/Python](https://github.com/metrue/fx/tree/master/examples/functions/Python) |
| Ruby | Supported | fx | [/examples/Ruby](https://github.com/metrue/fx/tree/master/examples/functions/Ruby) |
| Java | Supported | fx | [/examples/Java](https://github.com/metrue/fx/tree/master/examples/functions/Java) |
| 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) |
| D | Supported | [@andre2007](https://github.com/andre2007)| [/examples/D](https://github.com/metrue/fx/tree/master/examples/functions/D) |
| R | Working on [need your help](https://github.com/metrue/fx/issues/31) | ||
##### Requirements
* Docker: make sure [Docker](https://docs.docker.com/engine/installation/) installed and running on your server.
* dep: fx project uses [dep](https://github.com/golang/dep) to do the golang dependency management.
# Installation
##### Build and Run
* MacOS
```
$ git clone https://github.com/metrue/fx.git
$ cd fx
$ dep ensure
$ go install ./
brew tap metrue/homebrew-fx
brew install metrue/fx/fx
```
* start server
* Linux/Unix
```
fx serve
via cURL
```shell
# Install to local directory
curl -o- https://raw.githubusercontent.com/metrue/fx/master/scripts/install.sh | bash
# Install to /usr/local/bin/
curl -o- https://raw.githubusercontent.com/metrue/fx/master/scripts/install.sh | sudo bash
```
now you can make a function to service in a second.
fx will be installed into /usr/local/bin, sometimes you may need `source ~/.zshrc` or `source ~/.bashrc` to make fx available in `$PAHT`.
* Window
You can go the release page to [download](https://github.com/metrue/fx/releases) fx manually;
## Usage
Make sure [Docker](https://docs.docker.com/engine/installation/) installed and running on your server first. then type `fx -h` on your terminal to check out basic help.
```
fx up ./examples/functions/func.js
NAME:
fx - makes function as a service
USAGE:
fx [global options] command [command options] [arguments...]
VERSION:
0.6.0
COMMANDS:
infra manage infrastructure of fx
image manage image of service
doctor health check for fx
up deploy a function or a group of functions
down destroy a service
list, ls list deployed services
call run a function instantly
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--help, -h show help
--version, -v print the version
```
the function defined in *examples/functions/func.js* is quite simple, it calculates the sum of two numbers then returns:
1. List your current machines and activate you machine
```shell
$ fx infra ls # list machines
{
"localhost": {
"Host": "localhost",
"User": "",
"Password": "",
"Enabled": true,
"Provisioned": false
}
}
$ fx infra activate localhost # activate 'localhost'
2019/08/10 13:21:20 info Provision:pull python Docker base iamge: ✓
2019/08/10 13:21:21 info Provision:pull d Docker base image: ✓
2019/08/10 13:21:23 info Provision:pull java Docker base image: ✓
2019/08/10 13:21:28 info Provision:pull julia Docker base image: ✓
2019/08/10 13:21:31 info Provision:pull node Docker base image: ✓
2019/08/10 13:22:09 info Provision:pull go Docker base image: ✓
2019/08/10 13:22:09 info provision machine localhost: ✓
2019/08/10 13:22:09 info enble machine localhost: ✓
```
module.exports = (input) => {
return parseInt(input.a, 10) + parseInt(input.b, 10)
It may take seconds since `fx` needs to download some basic resources
*Note* you can add a remote host as fx machine also,
```
$ fx infra add --name my_aws_vm --host 13.121.202.227 --user root --password yourpassword
$ fx infra list
{
"my_aws_vm": {
"Host": "13.121.202.227",
"User": "root",
"Password": "yourpassword",
"Enabled": false,
"Provisioned": false
},
"localhost": {
"Host": "localhost",
"User": "",
"Password": "",
"Enabled": true,
"Provisioned": true
}
}
$ fx infra activate my_aws_vm
```
then your function will be deployed onto remote host also.
2. Write a function
You can check out [examples](https://github.com/metrue/fx/tree/master/examples/functions) for reference. Let's write a function as an example, it calculates the sum of two numbers then returns:
```js
module.exports = (ctx) => {
ctx.body = 'hello world'
}
```
Then save it to a file `func.js`.
3. Deploy your function as a service
Give your service a port with `--port`, and name with `--name`, heath checking with `--healthcheck` if you want.
```shell
$ fx up -name fx_service_name -p 10001 --healthcheck func.js
2019/08/10 13:26:37 info Pack Service: ✓
2019/08/10 13:26:39 info Build Service: ✓
2019/08/10 13:26:39 info Run Service: ✓
2019/08/10 13:26:39 info Service (fx_service_name) is running on: 0.0.0.0:10001
2019/08/10 13:26:39 info up function fx_service_name(func.js) to machine localhost: ✓
```
if you want see what the source code of your service looks like, you can export it into a dirctory,
```shell
$ fx image export -o <path of dir> func.js
2019/09/25 19:31:19 info exported to <path of dir>: ✓
```
4. Test your service
then you can test your service:
```
curl -X POST <service url> -H "Content-Type: application/json" -d '{"a": 1, "b": 1}'
```shell
$ curl -v 0.0.0.0:10001
GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: 0.0.0.0:10001
User-Agent: HTTPie/1.0.2
HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 11
Content-Type: text/plain; charset=utf-8
Date: Sat, 10 Aug 2019 05:28:03 GMT
hello world
```
of course you can do more.
```
Usage:
$ fx serve start f(x) server
$ fx up func1.js func2.py func3.go ... deploy a function or a group of functions
$ fx down [service ID] ... destroy a function or a group of functions
$ fx list list deployed services
$ fx --version show current version of f(x)
## Docker
TODO
## Kubernetes
**fx** supports deploy function to be a service onto Kubernetes cluster infrasture, and we encourage you to do that other than on bare Docker environment, there are lots of advantage to run your function on Kubernetes like self-healing, load balancing, easy horizontal scaling, etc. It's pretty simple to deploy your function onto Kubernetes with **fx**, you just set KUBECONFIG in your enviroment.
```shell
KUBECONFIG=<Your KUBECONFIG> fx deploy -n fx-service-abc_js -p 12349 examples/functions/JavaScript/func.js # function will be deploy to your Kubernetes cluster and expose a IP address of your loadbalencer
```
#### How to write your function
or
functions example with Go, Ruby, Python, Node, PHP.
* Go
```
package main
type Input struct {
A int32
B int32
}
type Output struct {
Sum int32
}
func Fx(input *Input) (output *Output) {
output = &Output{
Sum: input.A + input.B,
}
return
}
```shell
$ export KUBECONFIG=<Your KUBECONFIG>
$ fx deploy -n fx-service-abc_js -p 12349 examples/functions/JavaScript/func.js # function will be deploy to your Kubernetes cluster and expose a IP address of your loadbalencer
```
* Ruby
```
def fx(input)
return input['a'] + input['b']
end
* Local Kubernetes Cluster
Docker for Mac and Docker for Windows already support Kubernetes with single node cluster, we can use it directly, and the default `KUBECONFIG` is `~/.kube/config`.
```shell
$ export KUBECONFIG=~/.kube/config # then fx will take the config to deloy function
```
* Python
```
def fx(input):
return input['a'] + input['b']
if you have multiple Kubernetes clusters configured, you have to set context correctly. FYI [configure-access-multiple-clusters](https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/)
* Azure Kubernetes Service (AKS)
You should create a Kubernetes cluster if you don't have one on AKS, detail document can found [here](https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough).
```shell
$ az group create --name <myResourceGroup> --location eastus
$ az aks create --resource-group <myResourceGroup> --name myAKSCluster --node-count <count>
$ az aks get-credentials --resource-group <myResourceGroup> --name <myAKSCluster>
```
* Node
```
module.exports = (input) => {
return parseInt(input.a, 10) + parseInt(input.b, 10)
}
Then you can verify it with `kubectl`,
```shell
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
aks-nodepool1-31718369-0 Ready agent 6m44s v1.12.8
```
* PHP
```
<?php
function Fx($input) {
return $input["a"]+$input["b"];
}
Since AKS's config will be merged into `~/.kube/config` and set to be current context after you run `az aks get-credentials` command, so you can just set KUBECONFIG to default config also,
```shell
$ export KUBECONFIG=~/.kube/config # then fx will take the config to deloy function
```
* Julia
```
struct Input
a::Number
b::Number
end
But we would suggest you run `kubectl config current-context` to check if the current context is what you want.
fx = function(input::Input)
return input.a + input.b
end
* Amazon Elastic Kubernetes Service (EKS)
TODO
* Google Kubernetes Engine (GKET)
TODO
## Contribute
fx uses [Project](https://github.com/metrue/fx/projects/4) to manage the development.
#### Prerequisites
Docker: make sure [Docker](https://docs.docker.com/engine/installation/) installed and running on your server.
#### Build & Test
```
$ git clone https://github.com/metrue/fx
$ cd fx
$ make build
```
### Contributors
Then you can build and test:
```
$ make build
$ ./build/fx -h
```
## Contributors
Thank you to all the people who already contributed to fx!
@@ -157,6 +307,12 @@ Thank you to all the people who already contributed to fx!
<a href="https://github.com/pplam" target="_blank">
<img alt="pplam" src="https://avatars2.githubusercontent.com/u/12783579?v=4&s=50" width="50">
</a>
<a href="https://github.com/muka" target="_blank">
<img alt="muka" src="https://avatars2.githubusercontent.com/u/1021269?v=4&s=50" width="50">
</a>
<a href="https://github.com/xwjdsh" target="_blank">
<img alt="xwjdsh" src="https://avatars2.githubusercontent.com/u/11025519?v=4&s=50" width="50">
</a>
<a href="https://github.com/mbesancon" target="_blank">
<img alt="mbesancon" src="https://avatars2.githubusercontent.com/u/7623090?v=4&s=50" width="50">
</a>
@@ -169,10 +325,12 @@ Thank you to all the people who already contributed to fx!
<a href="https://github.com/chlins" target="_blank">
<img alt="chlins" src="https://avatars2.githubusercontent.com/u/31262637?v=4&s=50" width="50">
</a>
<a href="https://github.com/andre2007" target="_blank">
<img alt="andre2007" src="https://avatars1.githubusercontent.com/u/1451047?s=50&v=4" width="50">
</a>
<a href="https://github.com/steventhanna" target="_blank">
<img alt="andre2007" src="https://avatars1.githubusercontent.com/u/2541678?s=50&v=4" width="50">
</a>
</tr>
</tbody>
</table>
### LICENSE
MIT

5
assets/dockerfiles/base/d/Dockerfile vendored Normal file
View File

@@ -0,0 +1,5 @@
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y build-essential curl libcurl3 \
&& curl -OL http://downloads.dlang.org/releases/2.x/2.077.1/dmd_2.077.1-0_amd64.deb \
&& apt install ./dmd_2.077.1-0_amd64.deb

12
assets/dockerfiles/base/java/Dockerfile vendored Normal file
View File

@@ -0,0 +1,12 @@
FROM java:8
# Install maven
RUN apt-get update
RUN apt-get install -y maven
WORKDIR /code
# Prepare by downloading dependencies
ADD pom.xml /code/pom.xml
RUN ["mvn", "dependency:resolve"]
RUN ["mvn", "verify"]

3
assets/dockerfiles/base/java/Makefile vendored Normal file
View File

@@ -0,0 +1,3 @@
build:
docker build -t metrue/fx-java-base:latest .
docker push metrue/fx-java-base

51
assets/dockerfiles/base/java/pom.xml vendored Normal file
View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>fx-app-java</artifactId>
<packaging>jar</packaging>
<version>0.1.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>fx.app</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>io.javalin</groupId>
<artifactId>javalin</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20171018</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,3 @@
FROM julia:latest
RUN apt-get update && apt-get install -y gcc apt-utils unzip make libhttp-parser-dev

View File

@@ -0,0 +1,3 @@
build:
docker build -t metrue/fx-julia-base:latest .
docker push metrue/fx-julia-base

View File

@@ -0,0 +1,4 @@
FROM node:latest
COPY . .
RUN npm install

View File

@@ -3,6 +3,3 @@ FROM python:3
RUN pip install flask
ENV FLASK_APP=app.py
COPY . .
EXPOSE 3000
CMD flask run -h 0.0.0.0 -p 3000

970
assets/dockerfiles/base/rust/Cargo.lock generated vendored Normal file
View File

@@ -0,0 +1,970 @@
[[package]]
name = "base64"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "base64"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bytes"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cc"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cookie"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-utils"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "devise"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"devise_codegen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"devise_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "devise_codegen"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"devise_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "devise_core"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "filetime"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fsevent"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fsevent-sys"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "futures"
version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "httparse"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "hyper"
version = "0.10.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
"httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "idna"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "indexmap"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "inotify"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "inotify-sys"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "iovec"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "isatty"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itoa"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "language-tags"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazycell"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lock_api"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "matches"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mime"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mio"
version = "0.6.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mio-extras"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "miow"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "net2"
version = "0.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "notify"
version = "4.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
"fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num_cpus"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "owning_ref"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pear"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"pear_codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pear_codegen"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "percent-encoding"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "0.4.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redox_syscall"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ring"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rocket"
version = "0.4.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pear 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rocket_codegen 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rocket_http 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)",
"state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rocket_codegen"
version = "0.4.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"devise 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"rocket_http 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rocket_contrib"
version = "0.4.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rocket 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rocket_http"
version = "0.4.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)",
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"pear 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rust"
version = "0.1.0"
dependencies = [
"rocket 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rocket_contrib 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ryu"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "safemem"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "same-file"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "scopeguard"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_derive"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_json"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "slab"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "smallvec"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "stable_deref_trait"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "state"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "0.15.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-executor"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-io"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-reactor"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "toml"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "traitobject"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "typeable"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicase"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-bidi"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-normalization"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unreachable"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "untrusted"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "url"
version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "version_check"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "walkdir"
version = "2.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-util"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ws2_32-sys"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "yansi"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "yansi"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2"
"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa"
"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16"
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1465f8134efa296b4c19db34d909637cb2bf0f7aaf21299e23e18fa29ac557cf"
"checksum crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c55913cc2799171a550e307918c0a360e8c16004820291bf3b638969b4a01816"
"checksum devise 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e04ba2d03c5fa0d954c061fc8c9c288badadffc272ebb87679a89846de3ed3"
"checksum devise_codegen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "066ceb7928ca93a9bedc6d0e612a8a0424048b0ab1f75971b203d01420c055d7"
"checksum devise_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf41c59b22b5e3ec0ea55c7847e5f358d340f3a8d6d53a5cf4f1564967f96487"
"checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646"
"checksum fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bbbf71584aeed076100b5665ac14e3d85eeb31fdbb45fbd41ef9a682b5ec05"
"checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874"
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b"
"checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83"
"checksum hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "df0caae6b71d266b91b4a83111a61d2b94ed2e2bea024c532b933dcff867e58c"
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718"
"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0"
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
"checksum isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e31a8281fc93ec9693494da65fbf28c0c2aa60a2eaec25dc58e2f31952e95edc"
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311"
"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16"
"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0"
"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432"
"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
"checksum notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "873ecfd8c174964ae30f401329d140142312c8e5590719cf1199d5f1717d8078"
"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13"
"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5"
"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c"
"checksum pear 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c26d2b92e47063ffce70d3e3b1bd097af121a9e0db07ca38a6cc1cf0cc85ff25"
"checksum pear_codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "336db4a192cc7f54efeb0c4e11a9245394824cc3bcbd37ba3ff51240c35d7a6e"
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c"
"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372"
"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db"
"checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d"
"checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a"
"checksum rocket 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eaa997ea8de9b14112aa38b2b6a0ecf3e651ff2c08d2fdf384fa765b5f9c2c98"
"checksum rocket_codegen 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fc68f90452ac88c6c1e02a922a0a23ef0ade08f9af899056d0c919b25fa7768c"
"checksum rocket_contrib 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2cc6a37cb7a6256efe6648f2d0ab9978c49ab883909ea4fabefb81d7c685d841"
"checksum rocket_http 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c7d555ce896830602aedf4bce2eec8d64713d45a2492c5a3625c3faa5f719b0f"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9"
"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef"
"checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c"
"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811"
"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d"
"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db"
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
"checksum state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7345c971d1ef21ffdbd103a75990a15eb03604fc8b8852ca8cb418ee1a099028"
"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7"
"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
"checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde"
"checksum tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7392fe0a70d5ce0c882c4778116c519bd5dbaa8a7c3ae3d04578b3afafdcda21"
"checksum tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "502b625acb4ee13cbb3b90b8ca80e0addd263ddacf6931666ef751e610b07fb5"
"checksum toml 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "19782e145d5abefb03758958f06ea35f7b1d8421b534140e0238fd3d0bfd66e3"
"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f"
"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
"checksum yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d60c3b48c9cdec42fb06b3b84b5b087405e1fa1c644a1af3930e4dfafe93de48"
"checksum yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9fc79f4a1e39857fc00c3f662cbf2651c771f00e9c15fe2abc341806bd46bd71"

13
assets/dockerfiles/base/rust/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,13 @@
[package]
name = "rust"
version = "0.1.0"
authors = ["FrontMage <xbgxwh@outlook.com>"]
edition = "2018"
[dependencies]
rocket = "0.4.0-rc.2"
rocket_contrib = "0.4.0-rc.2"
serde_json = "1.0"
serde_derive = "1.0.70"
serde = "1.0.70"

View File

@@ -0,0 +1,7 @@
FROM liuchong/rustup
WORKDIR /usr/src/myapp
COPY . .
RUN cp ./config ~/.cargo/ && rustup default nightly && cargo build
EXPOSE 3000
CMD ["cargo", "run"]

View File

@@ -0,0 +1,5 @@
[development]
address = "0.0.0.0"
port = 3000
log = "normal"

6
assets/dockerfiles/base/rust/config vendored Normal file
View File

@@ -0,0 +1,6 @@
[source.crates-io]
registry = "https://github.com/rust-lang/crates.io-index"
replace-with = 'ustc'
[source.ustc]
registry = "git://mirrors.ustc.edu.cn/crates.io-index"

View File

@@ -0,0 +1,18 @@
pub mod fns {
#[derive(Serialize)]
pub struct Response {
pub result: i32,
}
#[derive(Deserialize)]
pub struct Request {
pub a: i32,
pub b: i32,
}
pub fn func(req: Request) -> Response {
Response {
result: req.a + req.b,
}
}
}

View File

@@ -0,0 +1,22 @@
#![feature(proc_macro_hygiene, decl_macro, plugin)]
#[macro_use]
extern crate rocket;
extern crate rocket_contrib;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
mod fns;
use rocket_contrib::json::Json;
#[post("/", format = "application/json", data = "<req>")]
fn index(req: Json<fns::fns::Request>) -> Json<fns::fns::Response> {
Json(fns::fns::func(req.0))
}
fn main() {
rocket::ignite().mount("/", routes![index]).launch();
}

View File

@@ -1,75 +0,0 @@
package common
import (
"flag"
"fmt"
"io/ioutil"
"net/url"
"os"
"path"
)
type argPtrs struct {
addr *string
help *bool
}
func SetupFlags(option string) (
args *argPtrs,
flagSet *flag.FlagSet,
) {
flagSet = flag.NewFlagSet(option, flag.ExitOnError)
args = &argPtrs{
addr: flagSet.String(
"addr",
"localhost:8080",
"Server address.",
),
help: flagSet.Bool(
"help",
false,
"Help information.",
),
}
return
}
func ParseArgs(
option string,
s []string,
ptrs *argPtrs,
fs *flag.FlagSet,
) (funcs []string, addr string) {
home := os.Getenv("HOME")
configFile := path.Join(home, ".fx")
buf, _ := ioutil.ReadFile(configFile)
if len(buf) > 0 {
fs.Set("addr", string(buf))
}
fs.Parse(s)
if *(ptrs.help) {
FlagsAndExit(fs)
}
u := url.URL{
Scheme: "ws",
Host: *(ptrs.addr),
Path: "/" + option,
}
addr = u.String()
if fs.NFlag() == 0 {
funcs = s
} else {
funcs = fs.Args()
}
return
}
func FlagsAndExit(fs *flag.FlagSet) {
fmt.Println("Flags:")
fs.PrintDefaults()
os.Exit(0)
}

View File

@@ -1,63 +0,0 @@
package down
import (
"fmt"
"os"
"strings"
"github.com/gorilla/websocket"
"github.com/metrue/fx/commands/common"
)
func Down() {
option := "down"
nArgs := len(os.Args)
args, flagSet := common.SetupFlags(option)
if nArgs == 2 {
common.FlagsAndExit(flagSet)
}
functions, address := common.ParseArgs(
option,
os.Args[2:],
args,
flagSet,
)
dialer := websocket.Dialer{}
conn, _, err := dialer.Dial(address, nil)
if checkErr(err) {
return
}
defer conn.Close()
err = conn.WriteMessage(
websocket.TextMessage,
[]byte(strings.Join(functions, " ")),
)
if checkErr(err) {
return
}
for {
_, msg, err := conn.ReadMessage()
if err != nil {
if websocket.IsCloseError(err, 1000) {
return
}
fmt.Println(err)
if websocket.IsUnexpectedCloseError(err, 1000) {
return
}
continue
}
fmt.Println(string(msg))
}
}
func checkErr(err error) bool {
if err != nil {
fmt.Println(err)
return true
}
return false
}

View File

@@ -1,64 +0,0 @@
package list
import (
"fmt"
"os"
"strings"
"github.com/gorilla/websocket"
"github.com/metrue/fx/commands/common"
)
// List lists all running function services
func List() {
option := "list"
nArgs := len(os.Args)
args, flagSet := common.SetupFlags(option)
if nArgs < 2 {
common.FlagsAndExit(flagSet)
}
functions, address := common.ParseArgs(
option,
os.Args[2:],
args,
flagSet,
)
dialer := websocket.Dialer{}
conn, _, err := dialer.Dial(address, nil)
if checkErr(err) {
return
}
defer conn.Close()
err = conn.WriteMessage(
websocket.TextMessage,
[]byte(strings.Join(functions, " ")),
)
if checkErr(err) {
return
}
for {
_, msg, err := conn.ReadMessage()
if err != nil {
if websocket.IsCloseError(err, 1000) {
return
}
fmt.Println(err)
if websocket.IsUnexpectedCloseError(err, 1000) {
return
}
continue
}
fmt.Println(string(msg))
}
}
func checkErr(err error) bool {
if err != nil {
fmt.Println(err)
return true
}
return false
}

View File

@@ -1,35 +0,0 @@
package up
import (
"log"
"os"
)
// Logger is a customer wrapped logger
type Logger struct {
base *log.Logger
log.Logger
}
// Log outputs an object to stdout
func (l *Logger) Log(v interface{}) {
l.base.SetOutput(os.Stdout)
l.base.Print(v)
}
// Err outputs an object to stderr
func (l *Logger) Err(v interface{}) {
l.base.SetOutput(os.Stderr)
l.base.Print(v)
}
// NewLogger creates a new wrapped log.Logger with default values
func NewLogger(prefix string) *Logger {
return &Logger{
base: log.New(
os.Stdout,
prefix,
log.LstdFlags,
),
}
}

View File

@@ -1,69 +0,0 @@
package up
import (
"fmt"
"log"
"os"
"path/filepath"
"github.com/gorilla/websocket"
"github.com/metrue/fx/commands/common"
"github.com/metrue/fx/config"
)
// Up starts the functions specified in flags
func Up() {
option := "up"
nArgs := len(os.Args)
args, flagSet := common.SetupFlags(option)
if nArgs == 2 {
common.FlagsAndExit(flagSet)
}
functions, address := common.ParseArgs(
option,
os.Args[2:],
args,
flagSet,
)
fmt.Println("Deploy starting...")
dialer := websocket.Dialer{}
channel := make(chan bool)
defer close(channel)
numSuccess := 0
numFail := 0
for _, function := range functions {
conn, _, err := dialer.Dial(address, nil)
if err != nil {
log.Print(err)
numFail++
continue
}
lang := config.ExtLangMap[filepath.Ext(function)]
worker := NewWorker(function, lang, conn, channel)
go worker.Work()
}
// Loop until all function deploy done
loop:
for {
select {
case status := <-channel:
if status {
numSuccess++
} else {
numFail++
}
default:
if numSuccess+numFail == len(functions) {
fmt.Printf("Succed: %d\n", numSuccess)
fmt.Printf("Failed: %d\n", numFail)
fmt.Println("All deploy done!")
break loop
}
}
}
}

View File

@@ -1,147 +0,0 @@
package up
import (
"fmt"
"io"
"os"
"os/signal"
"github.com/gorilla/websocket"
)
// Worker handles a functional service
type Worker struct {
conn *websocket.Conn
ch chan<- bool
src string
lang string
logger *Logger
dead bool
}
// NewWorker creates and returns a new worker
func NewWorker(src, lang string, conn *websocket.Conn, ch chan<- bool) *Worker {
worker := &Worker{
src: src,
lang: lang,
conn: conn,
ch: ch,
logger: NewLogger("[" + src + "]"),
}
worker.conn.SetCloseHandler(worker.closeHandler)
return worker
}
func (worker *Worker) checkErr(err error) bool {
if err != nil {
worker.logger.Err(err)
if !websocket.IsCloseError(err, 1000) {
worker.ch <- false
}
return true
}
return false
}
func (worker *Worker) closeHandler(
code int,
msg string,
) error {
worker.dead = true
if msg == "0" {
worker.ch <- true
worker.logger.Log(msg)
} else {
worker.ch <- false
worker.logger.Err(msg)
}
return nil
}
// Work starts and handles a function from Worker's information
func (worker *Worker) Work() {
if worker.dead {
return
}
logger := worker.logger
conn := worker.conn
logger.Log("Deploying...")
// Open function source file
file, err := os.Open(worker.src)
if worker.checkErr(err) {
return
}
defer file.Close()
// Send source language type
err = conn.WriteMessage(
websocket.TextMessage,
[]byte(worker.lang),
)
if worker.checkErr(err) {
return
}
// Get websocket connection writer
writer, err := conn.NextWriter(
websocket.TextMessage,
)
if worker.checkErr(err) {
return
}
// Send function source file
bytesSent, err := io.Copy(
writer,
file,
)
if worker.checkErr(err) {
return
}
logger.Log(
fmt.Sprintf(
"Sent bytes: %d",
bytesSent,
))
err = writer.Close()
if worker.checkErr(err) {
return
}
interrupt := make(chan os.Signal, 2)
signal.Notify(interrupt, os.Interrupt, os.Kill)
errChan := make(chan error)
msgChan := make(chan string)
readReply := func(
c *websocket.Conn,
msgCh chan<- string,
errCh chan<- error,
) {
_, msg, err := c.ReadMessage()
if err != nil {
errCh <- err
return
}
msgCh <- string(msg)
}
go readReply(conn, msgChan, errChan)
// Wait for deploy done
for {
select {
case <-interrupt:
closeMsg := websocket.FormatCloseMessage(1000, "1")
conn.WriteMessage(websocket.CloseMessage, closeMsg)
case newMsg := <-msgChan:
logger.Log(newMsg)
if worker.dead {
return
}
go readReply(conn, msgChan, errChan)
case newErr := <-errChan:
if worker.checkErr(newErr) {
return
}
}
}
}

View File

@@ -1,27 +1,213 @@
package config
import (
"fmt"
"os"
"path"
"github.com/spf13/viper"
)
// Server contains the server configuration information
var Server = map[string]string{
"host": "localhost",
"port": "8080",
// Configer interface
type Configer interface {
GetMachine(name string) (Host, error)
AddMachine(name string, host Host) error
RemoveHost(name string) error
ListActiveMachines() (map[string]Host, error)
ListMachines() (map[string]Host, error)
EnableMachine(name string) error
DisableMachine(name string) error
UpdateProvisionedStatus(name string, ok bool) error
}
// Client contains the local and remote paths to fetch cached images
var Client = map[string]string{
"cache_dir": path.Join(os.Getenv("HOME"), ".fx/"),
"remote_images_url": "https://raw.githubusercontent.com/metrue/fx/master/images.zip",
// Config config of fx
type Config struct {
dir string
}
var ExtLangMap = map[string]string {
".js": "node",
".go": "go",
".rb": "ruby",
".py": "python",
".php": "php",
".jl": "julia",
// New create a config
func New(dir string) *Config {
return &Config{dir: dir}
}
// Init config
func (c *Config) Init() error {
if err := os.MkdirAll(c.dir, os.ModePerm); err != nil {
return err
}
ext := "yaml"
name := "config"
viper.SetConfigType(ext)
viper.SetConfigName(name)
viper.AddConfigPath(c.dir)
// detect if file exists
configFilePath := path.Join(c.dir, name+"."+ext)
if _, err := os.Stat(configFilePath); os.IsNotExist(err) {
fd, err := os.Create(configFilePath)
if err != nil {
return err
}
fd.Close()
localhost := Host{
Host: "localhost",
Password: "",
User: "",
Enabled: true,
Provisioned: false,
}
viper.Set("hosts", map[string]Host{"localhost": localhost})
return viper.WriteConfig()
}
if err := viper.ReadInConfig(); err != nil {
return fmt.Errorf("fatal error config file: %s", err)
}
return nil
}
// GetMachine get host by name
func (c *Config) GetMachine(name string) (Host, error) {
var hosts map[string]Host
if err := viper.UnmarshalKey("hosts", &hosts); err != nil {
return Host{}, err
}
host, ok := hosts[name]
if !ok {
return Host{}, fmt.Errorf("no such host %v", name)
}
return host, nil
}
// ListActiveMachines list enabled machines
func (c *Config) ListActiveMachines() (map[string]Host, error) {
hosts, err := c.ListMachines()
if err != nil {
return map[string]Host{}, err
}
lst := map[string]Host{}
for name, h := range hosts {
if h.Enabled {
lst[name] = h
}
}
return lst, nil
}
// AddMachine add host
func (c *Config) AddMachine(name string, host Host) error {
if !viper.IsSet("hosts") {
viper.Set("hosts", map[string]Host{})
}
hosts, err := c.ListMachines()
if err != nil {
return err
}
hosts[name] = host
viper.Set("hosts", hosts)
return viper.WriteConfig()
}
// RemoveHost remote a host
func (c *Config) RemoveHost(name string) error {
hosts, err := c.ListMachines()
if err != nil {
return err
}
if len(hosts) == 1 {
return fmt.Errorf("only one host left now, at least one host required by fx")
}
if _, ok := hosts[name]; ok {
delete(hosts, name)
viper.Set("hosts", hosts)
return viper.WriteConfig()
}
return fmt.Errorf("no such host %s", name)
}
// ListMachines list hosts
func (c *Config) ListMachines() (map[string]Host, error) {
var hosts map[string]Host
if err := viper.UnmarshalKey("hosts", &hosts); err != nil {
return nil, err
}
return hosts, nil
}
// EnableMachine enable a machine, after machine enabled, function will be deployed onto it when ever `fx up` invoked
func (c *Config) EnableMachine(name string) error {
host, err := c.GetMachine(name)
if err != nil {
return err
}
host.Enabled = true
if !viper.IsSet("hosts") {
viper.Set("hosts", map[string]Host{})
}
hosts, err := c.ListMachines()
if err != nil {
return err
}
hosts[name] = host
viper.Set("hosts", hosts)
return viper.WriteConfig()
}
// DisableMachine disable a machine, after machine disabled, function will not be deployed onto it
func (c *Config) DisableMachine(name string) error {
host, err := c.GetMachine(name)
if err != nil {
return err
}
host.Enabled = false
if !viper.IsSet("hosts") {
viper.Set("hosts", map[string]Host{})
}
hosts, err := c.ListMachines()
if err != nil {
return err
}
hosts[name] = host
viper.Set("hosts", hosts)
return viper.WriteConfig()
}
// UpdateProvisionedStatus update provisioned status
func (c *Config) UpdateProvisionedStatus(name string, ok bool) error {
host, err := c.GetMachine(name)
if err != nil {
return err
}
host.Provisioned = ok
if !viper.IsSet("hosts") {
viper.Set("hosts", map[string]Host{})
}
hosts, err := c.ListMachines()
if err != nil {
return err
}
hosts[name] = host
viper.Set("hosts", hosts)
return viper.WriteConfig()
}
// IsMachineProvisioned check if machine provisioned
func (c *Config) IsMachineProvisioned(name string) bool {
host, err := c.GetMachine(name)
if err != nil {
return false
}
return host.Provisioned
}

98
config/config_test.go Normal file
View File

@@ -0,0 +1,98 @@
package config
import (
"os"
"reflect"
"testing"
)
func TestConfig(t *testing.T) {
configPath := "/tmp/.fx"
defer func() {
if err := os.RemoveAll(configPath); err != nil {
t.Fatal(err)
}
}()
c := New(configPath)
if err := c.Init(); err != nil {
t.Fatal(err)
}
hosts, err := c.ListMachines()
if err != nil {
t.Fatal(err)
}
if len(hosts) != 1 {
t.Fatalf("should have localhost as default machine")
}
host := hosts["localhost"]
if !reflect.DeepEqual(host, Host{Host: "localhost", Enabled: true}) {
t.Fatalf("should get %v but got %v", Host{Host: "localhost"}, host)
}
name := "remote-a"
h := Host{
Host: "192.168.1.1",
User: "user-a",
Password: "password-a",
Enabled: false,
}
if err := c.AddMachine(name, h); err != nil {
t.Fatal(err)
}
hosts, err = c.ListMachines()
if err != nil {
t.Fatal(err)
}
if len(hosts) != 2 {
t.Fatalf("should have %d machines now, but got %d", 2, len(hosts))
}
lst, err := c.ListActiveMachines()
if err != nil {
t.Fatal(err)
}
if len(lst) != 1 {
t.Fatalf("should only have %d machine enabled, but got %d", 1, len(lst))
}
if err := c.EnableMachine(name); err != nil {
t.Fatal(err)
}
lst, err = c.ListActiveMachines()
if err != nil {
t.Fatal(err)
}
if len(lst) != 2 {
t.Fatalf("should only have %d machine enabled, but got %d", 2, len(lst))
}
h.Enabled = true
if !reflect.DeepEqual(lst[name], h) {
t.Fatalf("should get %v but got %v", h, lst[name])
}
if lst[name].Provisioned != false {
t.Fatalf("should get %v but got %v", false, lst[name].Provisioned)
}
if err := c.UpdateProvisionedStatus(name, true); err != nil {
t.Fatal(err)
}
updatedHost, err := c.GetMachine(name)
if err != nil {
t.Fatal(err)
}
if updatedHost.Provisioned != true {
t.Fatalf("should get %v but got %v", true, updatedHost.Provisioned)
}
}

40
config/host.go Normal file
View File

@@ -0,0 +1,40 @@
package config
// Host host entity
type Host struct {
Host string
User string
Password string
Enabled bool
Provisioned bool
}
// NewHost new a host
func NewHost(addr, user, password string) Host {
return Host{
Host: addr,
User: user,
Password: password,
Enabled: false,
Provisioned: false,
}
}
// Valid if host is valid
func (h Host) Valid() bool {
// TODO stronger check
return h.Host != ""
}
// IsLocal if host is localhost
func (h Host) IsLocal() bool {
if !h.Valid() {
return false
}
return h.Host == "127.0.0.1" || h.Host == "localhost"
}
// IsRemote is host is remote
func (h Host) IsRemote() bool {
return !h.IsLocal()
}

149
config/mocks/config.go Normal file
View File

@@ -0,0 +1,149 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: ./config.go
// Package mock_config is a generated GoMock package.
package mock_config
import (
gomock "github.com/golang/mock/gomock"
config "github.com/metrue/fx/config"
reflect "reflect"
)
// MockConfiger is a mock of Configer interface
type MockConfiger struct {
ctrl *gomock.Controller
recorder *MockConfigerMockRecorder
}
// MockConfigerMockRecorder is the mock recorder for MockConfiger
type MockConfigerMockRecorder struct {
mock *MockConfiger
}
// NewMockConfiger creates a new mock instance
func NewMockConfiger(ctrl *gomock.Controller) *MockConfiger {
mock := &MockConfiger{ctrl: ctrl}
mock.recorder = &MockConfigerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use
func (m *MockConfiger) EXPECT() *MockConfigerMockRecorder {
return m.recorder
}
// GetMachine mocks base method
func (m *MockConfiger) GetMachine(name string) (config.Host, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetMachine", name)
ret0, _ := ret[0].(config.Host)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetMachine indicates an expected call of GetMachine
func (mr *MockConfigerMockRecorder) GetMachine(name interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMachine", reflect.TypeOf((*MockConfiger)(nil).GetMachine), name)
}
// AddMachine mocks base method
func (m *MockConfiger) AddMachine(name string, host config.Host) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddMachine", name, host)
ret0, _ := ret[0].(error)
return ret0
}
// AddMachine indicates an expected call of AddMachine
func (mr *MockConfigerMockRecorder) AddMachine(name, host interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddMachine", reflect.TypeOf((*MockConfiger)(nil).AddMachine), name, host)
}
// RemoveHost mocks base method
func (m *MockConfiger) RemoveHost(name string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "RemoveHost", name)
ret0, _ := ret[0].(error)
return ret0
}
// RemoveHost indicates an expected call of RemoveHost
func (mr *MockConfigerMockRecorder) RemoveHost(name interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveHost", reflect.TypeOf((*MockConfiger)(nil).RemoveHost), name)
}
// ListActiveMachines mocks base method
func (m *MockConfiger) ListActiveMachines() (map[string]config.Host, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ListActiveMachines")
ret0, _ := ret[0].(map[string]config.Host)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ListActiveMachines indicates an expected call of ListActiveMachines
func (mr *MockConfigerMockRecorder) ListActiveMachines() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListActiveMachines", reflect.TypeOf((*MockConfiger)(nil).ListActiveMachines))
}
// ListMachines mocks base method
func (m *MockConfiger) ListMachines() (map[string]config.Host, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ListMachines")
ret0, _ := ret[0].(map[string]config.Host)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ListMachines indicates an expected call of ListMachines
func (mr *MockConfigerMockRecorder) ListMachines() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListMachines", reflect.TypeOf((*MockConfiger)(nil).ListMachines))
}
// EnableMachine mocks base method
func (m *MockConfiger) EnableMachine(name string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "EnableMachine", name)
ret0, _ := ret[0].(error)
return ret0
}
// EnableMachine indicates an expected call of EnableMachine
func (mr *MockConfigerMockRecorder) EnableMachine(name interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnableMachine", reflect.TypeOf((*MockConfiger)(nil).EnableMachine), name)
}
// DisableMachine mocks base method
func (m *MockConfiger) DisableMachine(name string) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DisableMachine", name)
ret0, _ := ret[0].(error)
return ret0
}
// DisableMachine indicates an expected call of DisableMachine
func (mr *MockConfigerMockRecorder) DisableMachine(name interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DisableMachine", reflect.TypeOf((*MockConfiger)(nil).DisableMachine), name)
}
// UpdateProvisionedStatus mocks base method
func (m *MockConfiger) UpdateProvisionedStatus(name string, ok bool) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateProvisionedStatus", name, ok)
ret0, _ := ret[0].(error)
return ret0
}
// UpdateProvisionedStatus indicates an expected call of UpdateProvisionedStatus
func (mr *MockConfigerMockRecorder) UpdateProvisionedStatus(name, ok interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateProvisionedStatus", reflect.TypeOf((*MockConfiger)(nil).UpdateProvisionedStatus), name, ok)
}

34
constants/constants.go Normal file
View File

@@ -0,0 +1,34 @@
package constants
import (
"os"
"path"
)
// AgentPort fx server agent port
const AgentPort = "8866"
// BaseImages base images to build fx functions
var BaseImages = []string{
"metrue/fx-java-base",
"metrue/fx-julia-base",
"metrue/fx-python-base",
"metrue/fx-node-base",
"metrue/fx-d-base",
"metrue/fx-go-base",
}
// ConfigPath path to config
var ConfigPath = path.Join(os.Getenv("HOME"), ".fx")
// AgentContainerName fx agent name
const AgentContainerName = "fx-agent"
// CheckedSymbol check symbol ✓
const CheckedSymbol = "\u2713"
// UncheckedSymbol uncheck ✗
const UncheckedSymbol = "\u2717"
// FxContainerExposePort each fx container expose a default port 3000
const FxContainerExposePort = 3000

View File

@@ -1,4 +1,4 @@
FROM node:latest
FROM metrue/fx-node-base
COPY . .
EXPOSE 3000

View File

@@ -1,12 +1,9 @@
const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const func = require('./fx');
const fx = require('./fx');
const app = new Koa();
app.use(bodyParser());
app.use(ctx => {
const msg = func(ctx.request.body);
ctx.body = msg;
});
app.use(fx);
app.listen(3000);

View File

@@ -0,0 +1,3 @@
module.exports = (ctx) => {
ctx.body = 'hello world'
}

View File

@@ -0,0 +1,195 @@
package api
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strconv"
"strings"
"time"
dockerTypes "github.com/docker/docker/api/types"
"github.com/google/go-querystring/query"
"github.com/metrue/fx/types"
"github.com/metrue/fx/utils"
)
// API interact with dockerd http api
type API struct {
endpoint string
version string
}
// Create a API
func Create(host string, port string) (*API, error) {
version, err := utils.DockerVersion(host, port)
if err != nil {
return nil, err
}
endpoint := fmt.Sprintf("http://%s:%s/v%s", host, port, version)
return &API{
endpoint: endpoint,
version: version,
}, nil
}
// MustCreate a api object, panic if not
func MustCreate(host string, port string) *API {
version, err := utils.DockerVersion(host, port)
if err != nil {
panic(err)
}
endpoint := fmt.Sprintf("http://%s:%s/v%s", host, port, version)
return &API{
endpoint: endpoint,
version: version,
}
}
func (api *API) get(path string, qs string, v interface{}) error {
url := fmt.Sprintf("%s%s", api.endpoint, path)
if !strings.HasPrefix(url, "http") {
url = "http://" + url
}
if qs != "" {
url += "?" + qs
}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return err
}
client := &http.Client{Timeout: 20 * time.Second}
resp, err := client.Do(req)
if err != nil {
return err
}
if resp.StatusCode != 200 {
return fmt.Errorf("request %s failed: %d - %s", url, resp.StatusCode, resp.Status)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
err = json.Unmarshal(body, &v)
if err != nil {
return err
}
return nil
}
func (api *API) post(path string, body []byte, expectStatus int, v interface{}) error {
url := fmt.Sprintf("%s%s", api.endpoint, path)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
client := &http.Client{Timeout: 20 * time.Second}
resp, err := client.Do(req)
if err != nil {
return err
}
if resp.StatusCode != expectStatus {
return fmt.Errorf("request %s (%s) failed: %d - %s", url, string(body), resp.StatusCode, resp.Status)
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
err = json.Unmarshal(b, &v)
if err != nil {
return err
}
return nil
}
// List list service
func (api *API) list(name string) ([]types.Service, error) {
if name != "" {
info, err := api.inspect(name)
if err != nil {
return []types.Service{}, err
}
port, err := strconv.Atoi(info.HostConfig.PortBindings["3000/tcp"][0].HostPort)
if err != nil {
return []types.Service{}, err
}
return []types.Service{
types.Service{
Name: name,
Image: info.Image,
State: info.State.Status,
ID: info.ID,
Host: info.HostConfig.PortBindings["3000/tcp"][0].HostIP,
Port: port,
},
}, nil
}
type filterItem struct {
Status []string `json:"url,omitempty"`
Label []string `json:"label,omitempty"`
Name []string `json:"name,omitempty"`
}
type Filters struct {
Items string `url:"filters"`
}
filter := filterItem{
// Status: []string{"running"},
Label: []string{"belong-to=fx"},
}
q, err := json.Marshal(filter)
if err != nil {
return []types.Service{}, err
}
filters := Filters{Items: string(q)}
qs, err := query.Values(filters)
if err != nil {
return []types.Service{}, err
}
var containers []dockerTypes.Container
if err := api.get("/containers/json", qs.Encode(), &containers); err != nil {
return []types.Service{}, err
}
svs := make(map[string]types.Service)
for _, container := range containers {
// container name have extra forward slash
// https://github.com/moby/moby/issues/6705
if strings.HasPrefix(container.Names[0], fmt.Sprintf("/%s", name)) {
svs[container.Image] = types.Service{
Name: container.Names[0],
Image: container.Image,
ID: container.ID,
Host: container.Ports[0].IP,
Port: int(container.Ports[0].PublicPort),
State: container.State,
}
}
}
services := []types.Service{}
for _, s := range svs {
services = append(services, s)
}
return services, nil
}

View File

@@ -0,0 +1,89 @@
package api
import (
"testing"
"github.com/metrue/fx/config"
"github.com/metrue/fx/constants"
"github.com/metrue/fx/types"
)
func TestDockerHTTP(t *testing.T) {
host := config.Host{Host: "127.0.0.1"}
api, err := Create(host.Host, constants.AgentPort)
if err != nil {
t.Fatal(err)
}
serviceName := "a-test-service"
project := types.Project{
Name: serviceName,
Language: "node",
Files: []types.ProjectSourceFile{
types.ProjectSourceFile{
Path: "Dockerfile",
Body: `
FROM metrue/fx-node-base
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]`,
IsHandler: false,
},
types.ProjectSourceFile{
Path: "app.js",
Body: `
const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const func = require('./fx');
const app = new Koa();
app.use(bodyParser());
app.use(ctx => {
const msg = func(ctx.request.body);
ctx.body = msg;
});
app.listen(3000);`,
IsHandler: false,
},
types.ProjectSourceFile{
Path: "fx.js",
Body: `
module.exports = (input) => {
return input.a + input.b
}
`,
IsHandler: true,
},
},
}
service, err := api.Build(project)
if err != nil {
t.Fatal(err)
}
if err != nil {
t.Fatal(err)
}
if service.Name != serviceName {
t.Fatalf("should get %s but got %s", serviceName, service.Name)
}
if err := api.Run(9999, &service); err != nil {
t.Fatal(err)
}
services, err := api.list(serviceName)
if err != nil {
t.Fatal(err)
}
if len(services) != 1 {
t.Fatal("service number should be 1")
}
if err := api.Stop(serviceName); err != nil {
t.Fatal(err)
}
}

View File

@@ -0,0 +1,5 @@
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y build-essential curl libcurl3 \
&& curl -OL http://downloads.dlang.org/releases/2.x/2.077.1/dmd_2.077.1-0_amd64.deb \
&& apt install ./dmd_2.077.1-0_amd64.deb

View File

@@ -0,0 +1,12 @@
FROM golang:1.12.0-alpine3.9 AS builder
LABEL maintainer="h.minghe@gmail.com"
ENV GO111MODULE on
ENV GOPROXY https://goproxy.io
ENV PATH $GOPATH/bin:$PATH
RUN go get "github.com/gin-gonic/gin"
RUN apk upgrade --no-cache \
&& apk add ca-certificates

View File

@@ -0,0 +1,12 @@
FROM java:8
# Install maven
RUN apt-get update
RUN apt-get install -y maven
WORKDIR /code
# Prepare by downloading dependencies
ADD pom.xml /code/pom.xml
RUN ["mvn", "dependency:resolve"]
RUN ["mvn", "verify"]

View File

@@ -0,0 +1,3 @@
build:
docker build -t metrue/fx-java-base:latest .
docker push metrue/fx-java-base

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>fx-app-java</artifactId>
<packaging>jar</packaging>
<version>0.1.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>fx.app</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>io.javalin</groupId>
<artifactId>javalin</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20171018</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,3 @@
FROM julia:latest
RUN apt-get update && apt-get install -y gcc apt-utils unzip make libhttp-parser-dev

View File

@@ -0,0 +1,3 @@
build:
docker build -t metrue/fx-julia-base:latest .
docker push metrue/fx-julia-base

View File

@@ -0,0 +1,4 @@
FROM node:latest
COPY . .
RUN npm install

View File

@@ -0,0 +1,22 @@
{
"name": "aok",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"redis": "^2.8.0",
"node-fetch": "^2.6.0",
"is-generator-function": "^1.0.6",
"koa": "^2.3.0",
"koa-bodyparser": "^4.2.0"
},
"devDependencies": {
"get-port-cli": "^1.1.0"
}
}

View File

@@ -0,0 +1,5 @@
FROM python:3
RUN pip install flask
ENV FLASK_APP=app.py

View File

@@ -0,0 +1,970 @@
[[package]]
name = "base64"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "base64"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bytes"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cc"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cookie"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "crossbeam-utils"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "devise"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"devise_codegen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"devise_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "devise_codegen"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"devise_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "devise_core"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "filetime"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fsevent"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fsevent-sys"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "futures"
version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "httparse"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "hyper"
version = "0.10.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
"httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "idna"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "indexmap"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "inotify"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "inotify-sys"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "iovec"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "isatty"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itoa"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "language-tags"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazycell"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lock_api"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "matches"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mime"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mio"
version = "0.6.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mio-extras"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "miow"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "net2"
version = "0.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "notify"
version = "4.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
"fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num_cpus"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "owning_ref"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parking_lot_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pear"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"pear_codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pear_codegen"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "percent-encoding"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "0.4.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redox_syscall"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ring"
version = "0.13.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rocket"
version = "0.4.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pear 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rocket_codegen 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rocket_http 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)",
"state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rocket_codegen"
version = "0.4.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"devise 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"rocket_http 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rocket_contrib"
version = "0.4.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"rocket 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rocket_http"
version = "0.4.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)",
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"pear 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rust"
version = "0.1.0"
dependencies = [
"rocket 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rocket_contrib 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ryu"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "safemem"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "same-file"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "scopeguard"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_derive"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_json"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "slab"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "smallvec"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "stable_deref_trait"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "state"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "0.15.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-executor"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-io"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tokio-reactor"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "toml"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "traitobject"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "typeable"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicase"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-bidi"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-normalization"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unreachable"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "untrusted"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "url"
version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "version_check"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "walkdir"
version = "2.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-util"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ws2_32-sys"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "yansi"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "yansi"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2"
"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d"
"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa"
"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16"
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1465f8134efa296b4c19db34d909637cb2bf0f7aaf21299e23e18fa29ac557cf"
"checksum crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c55913cc2799171a550e307918c0a360e8c16004820291bf3b638969b4a01816"
"checksum devise 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "74e04ba2d03c5fa0d954c061fc8c9c288badadffc272ebb87679a89846de3ed3"
"checksum devise_codegen 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "066ceb7928ca93a9bedc6d0e612a8a0424048b0ab1f75971b203d01420c055d7"
"checksum devise_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf41c59b22b5e3ec0ea55c7847e5f358d340f3a8d6d53a5cf4f1564967f96487"
"checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646"
"checksum fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bbbf71584aeed076100b5665ac14e3d85eeb31fdbb45fbd41ef9a682b5ec05"
"checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874"
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b"
"checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83"
"checksum hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "df0caae6b71d266b91b4a83111a61d2b94ed2e2bea024c532b933dcff867e58c"
"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e"
"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718"
"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0"
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
"checksum isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e31a8281fc93ec9693494da65fbf28c0c2aa60a2eaec25dc58e2f31952e95edc"
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311"
"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16"
"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0"
"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432"
"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40"
"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
"checksum notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "873ecfd8c174964ae30f401329d140142312c8e5590719cf1199d5f1717d8078"
"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13"
"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5"
"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c"
"checksum pear 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c26d2b92e47063ffce70d3e3b1bd097af121a9e0db07ca38a6cc1cf0cc85ff25"
"checksum pear_codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "336db4a192cc7f54efeb0c4e11a9245394824cc3bcbd37ba3ff51240c35d7a6e"
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c"
"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372"
"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db"
"checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d"
"checksum ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4db68a2e35f3497146b7e4563df7d4773a2433230c5e4b448328e31740458a"
"checksum rocket 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eaa997ea8de9b14112aa38b2b6a0ecf3e651ff2c08d2fdf384fa765b5f9c2c98"
"checksum rocket_codegen 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fc68f90452ac88c6c1e02a922a0a23ef0ade08f9af899056d0c919b25fa7768c"
"checksum rocket_contrib 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2cc6a37cb7a6256efe6648f2d0ab9978c49ab883909ea4fabefb81d7c685d841"
"checksum rocket_http 0.4.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c7d555ce896830602aedf4bce2eec8d64713d45a2492c5a3625c3faa5f719b0f"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9"
"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef"
"checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c"
"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811"
"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d"
"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db"
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
"checksum state 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7345c971d1ef21ffdbd103a75990a15eb03604fc8b8852ca8cb418ee1a099028"
"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7"
"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
"checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde"
"checksum tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7392fe0a70d5ce0c882c4778116c519bd5dbaa8a7c3ae3d04578b3afafdcda21"
"checksum tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "502b625acb4ee13cbb3b90b8ca80e0addd263ddacf6931666ef751e610b07fb5"
"checksum toml 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "19782e145d5abefb03758958f06ea35f7b1d8421b534140e0238fd3d0bfd66e3"
"checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
"checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f"
"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
"checksum yansi 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d60c3b48c9cdec42fb06b3b84b5b087405e1fa1c644a1af3930e4dfafe93de48"
"checksum yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9fc79f4a1e39857fc00c3f662cbf2651c771f00e9c15fe2abc341806bd46bd71"

View File

@@ -0,0 +1,13 @@
[package]
name = "rust"
version = "0.1.0"
authors = ["FrontMage <xbgxwh@outlook.com>"]
edition = "2018"
[dependencies]
rocket = "0.4.0-rc.2"
rocket_contrib = "0.4.0-rc.2"
serde_json = "1.0"
serde_derive = "1.0.70"
serde = "1.0.70"

View File

@@ -0,0 +1,14 @@
FROM liuchong/rustup
WORKDIR /usr/src/myapp
COPY . .
RUN cp ./config ~/.cargo/
RUN rustup default nightly
RUN cargo update
RUN cargo build
EXPOSE 3000
CMD ["cargo", "run"]

View File

@@ -0,0 +1,5 @@
[development]
address = "0.0.0.0"
port = 3000
log = "normal"

View File

@@ -0,0 +1,6 @@
[source.crates-io]
registry = "https://github.com/rust-lang/crates.io-index"
replace-with = 'ustc'
[source.ustc]
registry = "git://mirrors.ustc.edu.cn/crates.io-index"

View File

@@ -0,0 +1,18 @@
pub mod fns {
#[derive(Serialize)]
pub struct Response {
pub result: i32,
}
#[derive(Deserialize)]
pub struct Request {
pub a: i32,
pub b: i32,
}
pub fn func(req: Request) -> Response {
Response {
result: req.a + req.b,
}
}
}

View File

@@ -0,0 +1,22 @@
#![feature(proc_macro_hygiene, decl_macro, plugin)]
#[macro_use]
extern crate rocket;
extern crate rocket_contrib;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
mod fns;
use rocket_contrib::json::Json;
#[post("/", format = "application/json", data = "<req>")]
fn index(req: Json<fns::fns::Request>) -> Json<fns::fns::Response> {
Json(fns::fns::func(req.0))
}
fn main() {
rocket::ignite().mount("/", routes![index]).launch();
}

View File

@@ -0,0 +1,60 @@
package api
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"time"
"github.com/apex/log"
"github.com/metrue/fx/types"
"github.com/metrue/fx/utils"
)
// Call function directly with given params
func (api *API) Call(file string, param string, project types.Project) error {
service, err := api.Build(project)
if err != nil {
log.Fatalf("Build Service: %v", err)
return err
}
log.Info("Build Service: \u2713")
if err := api.Run(9999, &service); err != nil {
log.Fatalf("Run Service: %v", err)
return err
}
log.Info("Run Service: \u2713")
params := utils.PairsToParams(strings.Fields(param))
body, err := json.Marshal(params)
if err != nil {
return err
}
// Wait 2 seconds for service startup
time.Sleep(time.Second * 2)
url := fmt.Sprintf("http://%s:%d", service.Host, service.Port)
r, err := http.NewRequest("POST", url, bytes.NewReader(body))
if err != nil {
return err
}
r.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 20 * time.Second}
resp, err := client.Do(r)
if err != nil {
log.Fatalf("Call Service: %v", err)
return err
}
buf, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatalf("Call Service: %v", err)
return err
}
log.Info("Call Service: \u2713")
return utils.OutputJSON(string(buf))
}

View File

@@ -0,0 +1,26 @@
package api
import (
"fmt"
dockerTypes "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
)
type containerInfo struct {
ID string `json:"Id"`
State dockerTypes.ContainerState `json:"State"`
Image string `json:"Image"`
HostConfig container.HostConfig `json:"HostConfig"`
}
func (api *API) inspect(identify string) (containerInfo, error) {
var info containerInfo
path := fmt.Sprintf("/containers/%s/json", identify)
if err := api.get(path, "", &info); err != nil {
return info, err
}
return info, nil
}

View File

@@ -0,0 +1 @@
package api

View File

@@ -0,0 +1,77 @@
package api
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"time"
"github.com/docker/docker/api/types/container"
)
// ContainerWait waits until the specified container is in a certain state
// indicated by the given condition, either "not-running" (default),
// "next-exit", or "removed".
//
// If this client's API version is before 1.30, condition is ignored and
// ContainerWait will return immediately with the two channels, as the server
// will wait as if the condition were "not-running".
//
// If this client's API version is at least 1.30, ContainerWait blocks until
// the request has been acknowledged by the server (with a response header),
// then returns two channels on which the caller can wait for the exit status
// of the container or an error if there was a problem either beginning the
// wait request or in getting the response. This allows the caller to
// synchronize ContainerWait with other calls, such as specifying a
// "next-exit" condition before issuing a ContainerStart request.
func (api *API) ContainerWait(
ctx context.Context,
containerID string,
condition container.WaitCondition,
timeout time.Duration,
) (<-chan container.ContainerWaitOKBody, <-chan error) {
resultC := make(chan container.ContainerWaitOKBody)
errC := make(chan error, 1)
query := url.Values{}
query.Set("condition", string(condition))
path := fmt.Sprintf("/containers/%s/wait?%s", containerID, query.Encode())
url := fmt.Sprintf("%s%s", api.endpoint, path)
request, err := http.NewRequest("POST", url, nil)
if err != nil {
errC <- err
return resultC, errC
}
client := &http.Client{Timeout: timeout}
if _, err = client.Do(request); err != nil {
errC <- err
return resultC, errC
}
go func() {
resp, err := client.Do(request)
if err != nil {
errC <- err
}
defer resp.Body.Close()
var res container.ContainerWaitOKBody
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
errC <- err
}
if err := json.Unmarshal(body, &res); err != nil {
errC <- err
}
resultC <- res
}()
return resultC, errC
}

View File

@@ -0,0 +1,28 @@
package api
import (
"sync"
"github.com/apex/log"
)
// Down destroy services
func (api *API) Down(names []string) error {
var wg sync.WaitGroup
for _, name := range names {
wg.Add(1)
go func(s string) {
if err := api.Stop(s); err != nil {
log.Fatalf("Down Service %s: %v", s, err)
} else {
log.Infof("Down Service %s: \u2713", s)
}
defer wg.Done()
}(name)
}
wg.Wait()
return nil
}

View File

@@ -0,0 +1,7 @@
package api
import "testing"
func TestDown(t *testing.T) {
}

View File

@@ -0,0 +1,22 @@
package api
import (
"github.com/apex/log"
"github.com/metrue/fx/utils"
)
// List services
func (api *API) List(name string) error {
services, err := api.list(name)
if err != nil {
log.Fatalf("List Services: %v", err)
return err
}
for _, service := range services {
if err := utils.OutputJSON(service); err != nil {
return err
}
}
return nil
}

View File

@@ -0,0 +1,58 @@
package api
import (
"encoding/json"
dockerTypes "github.com/docker/docker/api/types"
filters "github.com/docker/docker/api/types/filters"
"github.com/google/go-querystring/query"
)
// GetNetwork get a network
func (api *API) GetNetwork(name string) ([]dockerTypes.NetworkResource, error) {
path := "/networks"
var networks []dockerTypes.NetworkResource
arg := filters.NewArgs(filters.KeyValuePair{
Key: "name",
Value: name,
})
// opt := dockerTypes.NetworkListOptions{Filters: arg}
q, err := json.Marshal(arg)
if err != nil {
return networks, err
}
type Filters struct {
Items string `url:"filters"`
}
filters := Filters{Items: string(q)}
qs, err := query.Values(filters)
if err != nil {
return networks, err
}
if err := api.get(path, qs.Encode(), &networks); err != nil {
return networks, err
}
return networks, nil
}
// CreateNetwork create a network
func (api *API) CreateNetwork(name string) error {
path := "/networks/create"
ncReq := dockerTypes.NetworkCreateRequest{
Name: name,
}
body, err := json.Marshal(ncReq)
if err != nil {
return err
}
var resp dockerTypes.NetworkCreateResponse
if err := api.post(path, body, 201, resp); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,35 @@
package api
import (
"testing"
"github.com/golang/mock/gomock"
"github.com/metrue/fx/config"
"github.com/metrue/fx/constants"
gock "gopkg.in/h2non/gock.v1"
)
func TestNetwork(t *testing.T) {
defer gock.Off()
ctrl := gomock.NewController(t)
defer ctrl.Finish()
host := config.Host{Host: "127.0.0.1"}
api, err := Create(host.Host, constants.AgentPort)
if err != nil {
t.Fatal(err)
}
const network = "fx-net"
if err := api.CreateNetwork(network); err != nil {
t.Fatal(err)
}
nws, err := api.GetNetwork(network)
if err != nil {
t.Fatal(err)
}
if nws[0].Name != network {
t.Fatalf("should get %s but got %s", network, nws[0].Name)
}
}

View File

@@ -0,0 +1,119 @@
package api
import (
"bufio"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"time"
"github.com/apex/log"
"github.com/google/go-querystring/query"
"github.com/google/uuid"
"github.com/metrue/fx/types"
"github.com/metrue/fx/utils"
)
func makeTar(project types.Project, tarFilePath string) error {
dir, err := ioutil.TempDir("/tmp", "fx-build-dir")
if err != nil {
return err
}
defer os.RemoveAll(dir)
for _, file := range project.Files {
tmpfn := filepath.Join(dir, file.Path)
if err := utils.EnsureFile(tmpfn); err != nil {
return err
}
if err := ioutil.WriteFile(tmpfn, []byte(file.Body), 0666); err != nil {
return err
}
}
return utils.TarDir(dir, tarFilePath)
}
// Build build a project
func (api *API) Build(project types.Project) (types.Service, error) {
tarDir, err := ioutil.TempDir("/tmp", "fx-tar")
if err != nil {
return types.Service{}, err
}
defer os.RemoveAll(tarDir)
imageID := uuid.New().String()
tarFilePath := filepath.Join(tarDir, fmt.Sprintf("%s.tar", imageID))
if err := makeTar(project, tarFilePath); err != nil {
return types.Service{}, err
}
labels := map[string]string{
"belong-to": "fx",
}
if err := api.BuildImage(tarFilePath, imageID, labels); err != nil {
return types.Service{}, err
}
return types.Service{
Name: project.Name,
Image: imageID,
}, nil
}
// BuildImage build docker image
func (api *API) BuildImage(tarFile string, tag string, labels map[string]string) error {
dockerBuildContext, err := os.Open(tarFile)
if err != nil {
return err
}
defer dockerBuildContext.Close()
type buildQuery struct {
Labels string `url:"labels,omitempty"`
Tags string `url:"t,omitempty"`
Dockerfile string `url:"dockerfile,omitempty"`
}
// Apply default labels
labelsJSON, _ := json.Marshal(labels)
q := buildQuery{
Tags: tag,
Labels: string(labelsJSON),
Dockerfile: "Dockerfile",
}
qs, err := query.Values(q)
if err != nil {
return err
}
path := "/build"
url := fmt.Sprintf("%s%s?%s", api.endpoint, path, qs.Encode())
req, err := http.NewRequest("POST", url, dockerBuildContext)
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/x-tar")
client := &http.Client{Timeout: 600 * time.Second}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
scanner := bufio.NewScanner(resp.Body)
for scanner.Scan() {
if os.Getenv("DEBUG") != "" {
log.Infof(scanner.Text())
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,166 @@
package api
import (
"fmt"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strings"
"testing"
"github.com/metrue/fx/config"
"github.com/metrue/fx/constants"
"github.com/metrue/fx/types"
gock "gopkg.in/h2non/gock.v1"
)
func TestMakeTar(t *testing.T) {
serviceName := "mock-service-abc"
project := types.Project{
Name: serviceName,
Language: "node",
Files: []types.ProjectSourceFile{
types.ProjectSourceFile{
Path: "Dockerfile",
Body: `
FROM metrue/fx-node-base
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]`,
IsHandler: false,
},
types.ProjectSourceFile{
Path: "app.js",
Body: `
const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const func = require('./fx');
const app = new Koa();
app.use(bodyParser());
app.use(ctx => {
const msg = func(ctx.request.body);
ctx.body = msg;
});
app.listen(3000);`,
IsHandler: false,
},
types.ProjectSourceFile{
Path: "fx.js",
Body: `
module.exports = (input) => {
return input.a + input.b
}
`,
IsHandler: true,
},
},
}
tarDir, err := ioutil.TempDir("/tmp", "fx-tar")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tarDir)
tarFilePath := filepath.Join(tarDir, fmt.Sprintf("%s.tar", serviceName))
if err := makeTar(project, tarFilePath); err != nil {
t.Fatal(err)
}
file, err := os.Open(tarFilePath)
if err != nil {
t.Fatal(err)
}
stat, err := file.Stat()
if err != nil {
t.Fatal(err)
}
if stat.Name() != serviceName+".tar" {
t.Fatalf("should get %s but got %s", serviceName+".tar", stat.Name())
}
if stat.Size() <= 0 {
t.Fatalf("tarfile invalid: size %d", stat.Size())
}
}
func TestBuild(t *testing.T) {
defer gock.Off()
host := config.Host{Host: "127.0.0.1"}
api, err := Create(host.Host, constants.AgentPort)
if err != nil {
t.Fatal(err)
}
url := "http://" + host.Host + ":" + constants.AgentPort
gock.New(url).
Post("/v" + api.version + "/build").
AddMatcher(func(req *http.Request, ereq *gock.Request) (bool, error) {
if strings.Contains(req.URL.String(), "/v"+api.version+"/build") {
return true, nil
}
return false, nil
}).
Reply(200).
JSON(map[string]string{
"stream": "Step 1/5...",
})
serviceName := "mock-service-abc"
project := types.Project{
Name: serviceName,
Language: "node",
Files: []types.ProjectSourceFile{
types.ProjectSourceFile{
Path: "Dockerfile",
Body: `
FROM metrue/fx-node-base
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]`,
IsHandler: false,
},
types.ProjectSourceFile{
Path: "app.js",
Body: `
const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const func = require('./fx');
const app = new Koa();
app.use(bodyParser());
app.use(ctx => {
const msg = func(ctx.request.body);
ctx.body = msg;
});
app.listen(3000);`,
IsHandler: false,
},
types.ProjectSourceFile{
Path: "fx.js",
Body: `
module.exports = (input) => {
return input.a + input.b
}
`,
IsHandler: true,
},
},
}
service, err := api.Build(project)
if err != nil {
t.Fatal(err)
}
if service.Name != serviceName {
t.Fatalf("should get %s but got %s", serviceName, service.Name)
}
if service.Image == "" {
t.Fatal("service image should not be empty")
}
}

View File

@@ -0,0 +1,127 @@
package api
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"
"github.com/apex/log"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network"
"github.com/docker/go-connections/nat"
"github.com/metrue/fx/types"
"github.com/pkg/errors"
)
// ContainerCreateRequestPayload request paylaod
type ContainerCreateRequestPayload struct {
*container.Config
HostConfig *container.HostConfig
NetworkingConfig *network.NetworkingConfig
}
const fxNetworkName = "fx-net"
// Run a service
func (api *API) Run(port int, service *types.Service) error {
networks, err := api.GetNetwork(fxNetworkName)
if err != nil {
return errors.Wrapf(err, "get network failed: %s", err)
}
if len(networks) == 0 {
if err := api.CreateNetwork(fxNetworkName); err != nil {
return errors.Wrapf(err, "error create network: %s", err)
}
}
networks, _ = api.GetNetwork(fxNetworkName)
config := &container.Config{
Image: service.Image,
ExposedPorts: nat.PortSet{
"3000/tcp": struct{}{},
},
}
endpoint := &network.EndpointSettings{
NetworkID: networks[0].ID,
}
networkConfig := &network.NetworkingConfig{
EndpointsConfig: map[string]*network.EndpointSettings{
"fx-net": endpoint,
},
}
hostConfig := &container.HostConfig{
AutoRemove: true,
PortBindings: nat.PortMap{
"3000/tcp": []nat.PortBinding{
{
HostIP: types.DefaultHost,
HostPort: fmt.Sprintf("%d", port),
},
},
},
}
req := ContainerCreateRequestPayload{
Config: config,
HostConfig: hostConfig,
NetworkingConfig: networkConfig,
}
body, err := json.Marshal(req)
if err != nil {
return errors.Wrap(err, "error mashal container create req")
}
// create container
path := fmt.Sprintf("/containers/create?name=%s", service.Name)
var createRes container.ContainerCreateCreatedBody
if err := api.post(path, body, 201, &createRes); err != nil {
return errors.Wrap(err, "create container request failed")
}
if createRes.ID == "" {
return fmt.Errorf("container id is missing")
}
log.Infof("container %s created", service.Name)
// start container
path = fmt.Sprintf("/containers/%s/start", createRes.ID)
url := fmt.Sprintf("%s%s", api.endpoint, path)
request, err := http.NewRequest("POST", url, nil)
if err != nil {
return errors.Wrap(err, "error new container create request")
}
client := &http.Client{Timeout: 20 * time.Second}
resp, err := client.Do(request)
if err != nil {
return errors.Wrap(err, "error do start container request")
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
if len(b) != 0 {
msg := fmt.Sprintf("start container met issue: %s", string(b))
return errors.New(msg)
}
log.Infof("container %s started", service.Name)
info, err := api.inspect(createRes.ID)
if err != nil {
msg := fmt.Sprintf("inspect container %s error", service.Name)
return errors.Wrap(err, msg)
}
service.ID = info.ID
service.Host = info.HostConfig.PortBindings["3000/tcp"][0].HostIP
service.Port = port
service.State = info.State.Status
return nil
}

View File

@@ -0,0 +1,55 @@
package api
import (
"net/http"
"testing"
"github.com/golang/mock/gomock"
"github.com/metrue/fx/config"
"github.com/metrue/fx/constants"
"github.com/metrue/fx/types"
gock "gopkg.in/h2non/gock.v1"
)
func TestServiceRun(t *testing.T) {
defer gock.Off()
ctrl := gomock.NewController(t)
defer ctrl.Finish()
host := config.Host{Host: "127.0.0.1"}
api, err := Create(host.Host, constants.AgentPort)
if err != nil {
t.Fatal(err)
}
service := types.Service{
Name: "a-mock-service",
Image: "a-mock-image-id",
}
mockContainerID := "mock-container-id"
url := "http://" + host.Host + ":" + constants.AgentPort
gock.New(url).
Post("/v0.2.1/containers").
AddMatcher(func(req *http.Request, ereq *gock.Request) (m bool, e error) {
// TODO multiple matching not supported by gock
if req.URL.String() == url+"/v0.2.1/containers/"+mockContainerID+"/start" {
return true, nil
} else if req.URL.String() == url+"/v0.2.1/containers/create?name="+service.Name {
return true, nil
}
return false, nil
}).
Reply(201).
JSON(map[string]interface{}{
"Id": mockContainerID,
"Warnings": []string{},
})
// FIXME
if err := api.Run(9999, &service); err == nil {
t.Fatal(err)
}
}

View File

@@ -0,0 +1,24 @@
package api
import (
"fmt"
"net/http"
"time"
)
// Stop a container by name
func (api *API) Stop(name string) error {
path := fmt.Sprintf("/containers/%s/stop", name)
url := fmt.Sprintf("%s%s", api.endpoint, path)
request, err := http.NewRequest("POST", url, nil)
if err != nil {
return err
}
client := &http.Client{Timeout: 20 * time.Second}
_, err = client.Do(request)
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,39 @@
package api
import (
"net/http"
"strings"
"testing"
"github.com/golang/mock/gomock"
"github.com/metrue/fx/config"
"github.com/metrue/fx/constants"
gock "gopkg.in/h2non/gock.v1"
)
func TestStop(t *testing.T) {
defer gock.Off()
ctrl := gomock.NewController(t)
defer ctrl.Finish()
host := config.Host{Host: "127.0.0.1"}
api, err := Create(host.Host, constants.AgentPort)
if err != nil {
t.Fatal(err)
}
mockServiceName := "mock-service-name"
url := "http://" + host.Host + ":" + constants.AgentPort
gock.New(url).
Post("/v" + api.version + "/containers/" + mockServiceName + "/stop").
AddMatcher(func(req *http.Request, ereq *gock.Request) (m bool, e error) {
if strings.Contains(req.URL.String(), "/v"+api.version+"/containers/"+mockServiceName+"/stop") {
return true, nil
}
return false, nil
}).
Reply(204)
if err := api.Stop(mockServiceName); err != nil {
t.Fatal(err)
}
}

View File

@@ -0,0 +1,81 @@
package api
import (
"context"
"time"
"github.com/apex/log"
"github.com/docker/docker/api/types/container"
"github.com/metrue/fx/constants"
"github.com/metrue/fx/types"
)
// UpOptions options for up
type UpOptions struct {
Body []byte
Lang string
Name string
Port int
HealtCheck bool
Project types.Project
}
// Up up a source code of function to be a service
func (api *API) Up(opt UpOptions) error {
service, err := api.Build(opt.Project)
if err != nil {
log.Fatalf("Build Service %s: %v", opt.Name, err)
return err
}
log.Infof("Build Service %s: %s", opt.Name, constants.CheckedSymbol)
if err := api.Run(opt.Port, &service); err != nil {
log.Fatalf("Run Service: %v", err)
return err
}
log.Infof("Run Service: %s", constants.CheckedSymbol)
log.Infof("Service (%s) is running on: %s:%d", service.Name, service.Host, service.Port)
if opt.HealtCheck {
go func() {
resultC, errC := api.ContainerWait(
context.Background(),
service.ID,
container.WaitConditionNextExit,
20*time.Second,
)
for {
select {
case res := <-resultC:
var msg string
if res.Error != nil {
msg = res.Error.Message
}
log.Warnf("container exited: Code(%d) %s %s", res.StatusCode, msg, constants.UncheckedSymbol)
case err := <-errC:
log.Fatalf("wait container status exit: %s, %v", constants.UncheckedSymbol, err)
}
}
}()
trys := 0
for {
if trys > 2 {
break
}
info, err := api.inspect(service.ID)
if err != nil {
log.Fatalf("healt checking failed: %v", err)
}
if info.State.Running {
log.Info("service is running")
} else {
log.Warnf("service is %s", info.State.Status)
}
time.Sleep(1 * time.Second)
trys++
}
}
return nil
}

View File

@@ -0,0 +1,191 @@
package docker
import (
"bytes"
"context"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/apex/log"
dockerTypes "github.com/docker/docker/api/types"
dockerTypesContainer "github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"
"github.com/google/uuid"
containerruntimes "github.com/metrue/fx/container_runtimes"
"github.com/metrue/fx/types"
"github.com/metrue/fx/utils"
)
// Docker docker as image builder
type Docker struct {
*client.Client
}
// CreateClient create a docker instance
func CreateClient(ctx context.Context) (*Docker, error) {
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
return nil, err
}
cli.NegotiateAPIVersion(ctx)
return &Docker{cli}, nil
}
// BuildImage a directory to be a image
func (d *Docker) BuildImage(ctx context.Context, workdir string, name string) error {
tarDir, err := ioutil.TempDir("/tmp", "fx-tar")
if err != nil {
return err
}
defer os.RemoveAll(tarDir)
imageID := uuid.New().String()
tarFilePath := filepath.Join(tarDir, fmt.Sprintf("%s.tar", imageID))
if err := utils.TarDir(workdir, tarFilePath); err != nil {
return err
}
dockerBuildContext, err := os.Open(tarFilePath)
if err != nil {
return err
}
defer dockerBuildContext.Close()
options := dockerTypes.ImageBuildOptions{
Dockerfile: "Dockerfile",
Tags: []string{imageID, name},
Labels: map[string]string{
"belong-to": "fx",
},
}
resp, err := d.ImageBuild(ctx, dockerBuildContext, options)
if err != nil {
return err
}
defer resp.Body.Close()
if os.Getenv("DEBUG") != "" {
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
log.Info(string(body))
}
return nil
}
// PushImage push image to hub.docker.com
func (d *Docker) PushImage(ctx context.Context, name string) (string, error) {
username := os.Getenv("DOCKER_USERNAME")
password := os.Getenv("DOCKER_PASSWORD")
if username == "" || password == "" {
return "", fmt.Errorf("DOCKER_USERNAME and DOCKER_PASSWORD required for push image to registry")
}
// TODO support private registry, like Azure Container registry
authConfig := dockerTypes.AuthConfig{
Username: username,
Password: password,
}
encodedJSON, err := json.Marshal(authConfig)
if err != nil {
return "", err
}
nameWithTag := username + "/" + name
if err := d.ImageTag(ctx, name, nameWithTag); err != nil {
return "", err
}
options := dockerTypes.ImagePushOptions{
RegistryAuth: base64.URLEncoding.EncodeToString(encodedJSON),
}
resp, err := d.ImagePush(ctx, nameWithTag, options)
if err != nil {
return "", err
}
defer resp.Close()
if os.Getenv("DEBUG") != "" {
body, err := ioutil.ReadAll(resp)
if err != nil {
return "", err
}
log.Info(string(body))
}
return nameWithTag, nil
}
// InspectImage inspect a image
func (d *Docker) InspectImage(ctx context.Context, name string, img interface{}) error {
_, body, err := d.ImageInspectWithRaw(ctx, name)
if err != nil {
return err
}
rdr := bytes.NewReader(body)
return json.NewDecoder(rdr).Decode(&img)
}
// StartContainer create and start a container from given image
func (d *Docker) StartContainer(ctx context.Context, name string, image string, ports []types.PortBinding) error {
portSet := nat.PortSet{}
portMap := nat.PortMap{}
for _, binding := range ports {
bindings := []nat.PortBinding{
nat.PortBinding{
HostIP: types.DefaultHost,
HostPort: fmt.Sprintf("%d", binding.ServiceBindingPort),
},
}
port := nat.Port(fmt.Sprintf("%d/tcp", binding.ContainerExposePort))
portSet[port] = struct{}{}
portMap[port] = bindings
}
config := &dockerTypesContainer.Config{
Image: image,
ExposedPorts: portSet,
}
hostConfig := &dockerTypesContainer.HostConfig{
AutoRemove: true,
PortBindings: portMap,
}
resp, err := d.ContainerCreate(ctx, config, hostConfig, nil, name)
if os.Getenv("DEBUG") != "" {
body, err := json.Marshal(resp)
if err != nil {
return err
}
log.Info(string(body))
}
if err != nil {
return err
}
if err := d.ContainerStart(ctx, resp.ID, dockerTypes.ContainerStartOptions{}); err != nil {
return err
}
return nil
}
// StopContainer stop and remove container
func (d *Docker) StopContainer(ctx context.Context, name string) error {
return d.ContainerStop(ctx, name, nil)
}
// InspectContainer inspect a container
func (d *Docker) InspectContainer(ctx context.Context, name string, container interface{}) error {
return nil
}
var (
_ containerruntimes.ContainerRuntime = &Docker{}
)

View File

@@ -0,0 +1,59 @@
package docker
import (
"context"
"os"
"strings"
"testing"
"time"
dockerTypes "github.com/docker/docker/api/types"
)
func TestDocker(t *testing.T) {
ctx := context.Background()
cli, err := CreateClient(ctx)
if err != nil {
t.Fatal(err)
}
workdir := "../fixture"
name := "fx-test-docker-image"
if err := cli.BuildImage(ctx, workdir, name); err != nil {
t.Fatal(err)
}
// wait a while for image to be tagged successfully after build
time.Sleep(2 * time.Second)
var imgInfo dockerTypes.ImageInspect
if err := cli.InspectImage(ctx, name, &imgInfo); err != nil {
t.Fatal(err)
}
found := false
for _, t := range imgInfo.RepoTags {
slice := strings.Split(t, ":")
if slice[0] == name {
found = true
break
}
}
if !found {
t.Fatalf("should have built image with tag %s", name)
}
username := os.Getenv("DOCKER_USERNAME")
password := os.Getenv("DOCKER_PASSWORD")
if username == "" || password == "" {
t.Skip("Skip push image test since DOCKER_USERNAME and DOCKER_PASSWORD not set in environment variable")
}
img, err := cli.PushImage(ctx, name)
if err != nil {
t.Fatal(err)
}
expect := username + "/" + name
if img != expect {
t.Fatalf("should get %s but got %s", expect, img)
}
}

View File

@@ -0,0 +1,17 @@
package containerruntimes
import (
"context"
"github.com/metrue/fx/types"
)
// ContainerRuntime interface
type ContainerRuntime interface {
BuildImage(ctx context.Context, workdir string, name string) error
PushImage(ctx context.Context, name string) (string, error)
InspectImage(ct context.Context, name string, img interface{}) error
StartContainer(ctx context.Context, name string, image string, bindings []types.PortBinding) error
StopContainer(ctx context.Context, name string) error
InspectContainer(ctx context.Context, name string, container interface{}) error
}

View File

@@ -0,0 +1,3 @@
FROM docker
ADD ./build/docker_packer /usr/bin/docker_packer

View File

@@ -0,0 +1,21 @@
GOBIN ?= ./build
GIT_VERSION := $(shell git describe --tags)
VERSION ?= $(GIT_VERSION)
REPO ?= "metrue/fx-docker"
TAG ?= "latest"
build:
CGO_ENABLED=0 go build -ldflags "-X main.Version=$(VERSION)" -v -o $(GOBIN)/docker_packer main.go
linux-build:
CGO_ENABLED=0 GOOS=linux go build -ldflags "-X main.Version=$(VERSION)" -v -o $(GOBIN)/docker_packer main.go
docker-build:
docker build -t ${REPO}:${TAG} .
docker-publish:
docker push ${REPO}:${TAG}
test:
docker run -v /var/run/docker.sock:/var/run/docker.sock ${REPO}:${TAG} docker_packer 'eyJEb2NrZXJmaWxlIjoiRlJPTSBtZXRydWUvZngtbm9kZS1iYXNlXG5cbkNPUFkgLiAuXG5FWFBPU0UgMzAwMFxuQ01EIFtcIm5vZGVcIiwgXCJhcHAuanNcIl1cbiIsImFwcC5qcyI6ImNvbnN0IEtvYSA9IHJlcXVpcmUoJ2tvYScpO1xuY29uc3QgYm9keVBhcnNlciA9IHJlcXVpcmUoJ2tvYS1ib2R5cGFyc2VyJyk7XG5jb25zdCBmeCA9IHJlcXVpcmUoJy4vZngnKTtcblxuY29uc3QgYXBwID0gbmV3IEtvYSgpO1xuYXBwLnVzZShib2R5UGFyc2VyKCkpO1xuYXBwLnVzZShmeCk7XG5cbmFwcC5saXN0ZW4oMzAwMCk7XG4iLCJmeC5qcyI6IlxubW9kdWxlLmV4cG9ydHMgPSAoY3R4KSA9XHUwMDNlIHtcblx0Y3R4LmJvZHkgPSAnaGVsbG8gd29ybGQnXG59XG4ifQ==' app-hello
docker run --rm -d -p 3000:3000 --name test-app-hello-container app-hello
sleep 2
curl 127.0.0.1:3000
docker stop test-app-hello-container

View File

@@ -0,0 +1,80 @@
package main
import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"log"
"os"
"time"
dockerTypes "github.com/docker/docker/api/types"
runtime "github.com/metrue/fx/container_runtimes/docker/sdk"
"github.com/metrue/fx/packer"
"github.com/metrue/fx/utils"
)
// Version binary version
var Version = "0.0.1"
func init() {
// TODO clean it up
os.Setenv("DEBUG", "true")
}
func main() {
args := os.Args
if len(args) != 3 {
fmt.Println(`Usage:
docker_packer <encrypt_docker_project_source_tree> <image_name>
`)
return
}
meta := args[1]
name := args[2]
str, err := base64.StdEncoding.WithPadding(base64.StdPadding).DecodeString(meta)
if err != nil {
log.Fatalf("could decode meta: %s, %v", meta, err)
os.Exit(1)
}
var tree map[string]string
if err := json.Unmarshal([]byte(str), &tree); err != nil {
log.Fatalf("could not unmarshal meta: %s", meta)
os.Exit(1)
}
workdir := "/tmp/fx"
if err := packer.TreeToDir(tree, workdir); err != nil {
log.Fatalf("could not restore to dir: %v", err)
os.Exit(1)
}
defer os.RemoveAll(workdir)
ctx := context.Background()
dockerClient, err := runtime.CreateClient(ctx)
if err != nil {
log.Fatalf("could not create a docker client: %v", err)
os.Exit(1)
}
if err := dockerClient.BuildImage(ctx, workdir, name); err != nil {
log.Fatalf("could not build image: %s", err)
os.Exit(1)
}
nameWithTag := name + ":latest"
if err := dockerClient.ImageTag(ctx, name, nameWithTag); err != nil {
log.Fatalf("could tag image: %v", err)
os.Exit(1)
}
var imgInfo dockerTypes.ImageInspect
if err := utils.RunWithRetry(func() error {
return dockerClient.InspectImage(context.Background(), name, &imgInfo)
}, time.Second*1, 5); err != nil {
fmt.Printf("inspect image failed: %s", err)
}
fmt.Println("image built succcessfully")
}

15
deploy/deployer.go Normal file
View File

@@ -0,0 +1,15 @@
package deploy
import (
"context"
types "github.com/metrue/fx/types"
)
// Deployer make a image a service
type Deployer interface {
Deploy(ctx context.Context, fn types.Func, name string, bindings []types.PortBinding) error
Destroy(ctx context.Context, name string) error
Update(ctx context.Context, name string) error
GetStatus(ctx context.Context, name string) error
}

82
deploy/docker/docker.go Normal file
View File

@@ -0,0 +1,82 @@
package docker
import (
"context"
"fmt"
"log"
"os"
"time"
dockerTypes "github.com/docker/docker/api/types"
runtime "github.com/metrue/fx/container_runtimes/docker/sdk"
"github.com/metrue/fx/deploy"
"github.com/metrue/fx/packer"
"github.com/metrue/fx/types"
"github.com/metrue/fx/utils"
)
// Docker manage container
type Docker struct {
client *runtime.Docker
}
// CreateClient create a docker instance
func CreateClient(ctx context.Context) (*Docker, error) {
cli, err := runtime.CreateClient(ctx)
if err != nil {
return nil, err
}
return &Docker{client: cli}, nil
}
// Deploy create a Docker container from given image, and bind the constants.FxContainerExposePort to given port
func (d *Docker) Deploy(ctx context.Context, fn types.Func, name string, ports []types.PortBinding) error {
workdir := fmt.Sprintf("/tmp/fx-%d", time.Now().Unix())
defer os.RemoveAll(workdir)
if err := packer.PackIntoDir(fn, workdir); err != nil {
return err
}
if err := d.client.BuildImage(ctx, workdir, name); err != nil {
return err
}
nameWithTag := name + ":latest"
if err := d.client.ImageTag(ctx, name, nameWithTag); err != nil {
log.Fatalf("could tag image: %v", err)
return err
}
// when deploy a function on a bare Docker running without Kubernetes,
// image would be built on-demand on host locally, so there is no need to
// pull image from remote.
// But it takes some times waiting image ready after image built, we retry to make sure it ready here
var imgInfo dockerTypes.ImageInspect
if err := utils.RunWithRetry(func() error {
return d.client.InspectImage(ctx, name, &imgInfo)
}, time.Second*1, 5); err != nil {
return err
}
return d.client.StartContainer(ctx, name, name, ports)
}
// Update a container
func (d *Docker) Update(ctx context.Context, name string) error {
return nil
}
// Destroy stop and remove container
func (d *Docker) Destroy(ctx context.Context, name string) error {
return d.client.ContainerStop(ctx, name, nil)
}
// GetStatus get status of container
func (d *Docker) GetStatus(ctx context.Context, name string) error {
return nil
}
var (
_ deploy.Deployer = &Docker{}
)

View File

@@ -0,0 +1,47 @@
package docker
import (
"context"
"testing"
"time"
"github.com/metrue/fx/types"
)
func TestDocker(t *testing.T) {
ctx := context.Background()
cli, err := CreateClient(ctx)
if err != nil {
t.Fatal(err)
}
name := "helloworld"
bindings := []types.PortBinding{
types.PortBinding{
ServiceBindingPort: 80,
ContainerExposePort: 3000,
},
types.PortBinding{
ServiceBindingPort: 443,
ContainerExposePort: 3000,
},
}
fn := types.Func{
Language: "node",
Source: `
module.exports = (ctx) => {
ctx.body = 'hello world'
}
`,
}
if err := cli.Deploy(ctx, fn, name, bindings); err != nil {
t.Fatal(err)
}
time.Sleep(1 * time.Second)
if err := cli.Destroy(ctx, name); err != nil {
t.Fatal(err)
}
}

View File

@@ -0,0 +1,5 @@
FROM metrue/fx-node-base
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]

View File

@@ -0,0 +1,9 @@
const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const fx = require('./fx');
const app = new Koa();
app.use(bodyParser());
app.use(fx);
app.listen(3000);

View File

@@ -0,0 +1,3 @@
module.exports = (ctx) => {
ctx.body = 'hello world'
}

View File

@@ -0,0 +1,47 @@
package kubernetes
import (
apiv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// CreateConfigMap create a config map with data
func (k *K8S) CreateConfigMap(namespace string, name string, data map[string]string) (*apiv1.ConfigMap, error) {
cm := &apiv1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: data,
}
return k.CoreV1().ConfigMaps(namespace).Create(cm)
}
// DeleteConfigMap delete a config map
func (k *K8S) DeleteConfigMap(namespace string, name string) error {
return k.CoreV1().ConfigMaps(namespace).Delete(name, &metav1.DeleteOptions{})
}
// UpdateConfigMap update a config map
func (k *K8S) UpdateConfigMap(namespace string, name string, data map[string]string) (*apiv1.ConfigMap, error) {
cm := &apiv1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Data: data,
}
return k.CoreV1().ConfigMaps(namespace).Update(cm)
}
// GetConfigMap get a config map
func (k *K8S) GetConfigMap(namespace string, name string) (*apiv1.ConfigMap, error) {
return k.CoreV1().ConfigMaps(namespace).Get(name, metav1.GetOptions{})
}
// CreateOrUpdateConfigMap create or update a config map
func (k *K8S) CreateOrUpdateConfigMap(namespace string, name string, data map[string]string) (*apiv1.ConfigMap, error) {
_, err := k.GetConfigMap(namespace, name)
if err != nil {
return k.CreateConfigMap(namespace, name, data)
}
return k.UpdateConfigMap(namespace, name, data)
}

View File

@@ -0,0 +1,35 @@
package kubernetes
import (
"os"
"testing"
)
func TestConfigMap(t *testing.T) {
kubeconfig := os.Getenv("KUBECONFIG")
if kubeconfig == "" {
t.Skip("skip test since no KUBECONFIG given in environment variable")
}
k8s, err := Create()
if err != nil {
t.Fatal(err)
}
namespace := "default"
name := "test-configmap"
data := map[string]string{
"message": "hello world",
}
cm, err := k8s.CreateConfigMap(namespace, name, data)
if err != nil {
t.Fatal(err)
}
if cm.Name != name {
t.Fatalf("should get %s but got %s", name, cm.Name)
}
if err != k8s.DeleteConfigMap(namespace, name) {
t.Fatal(err)
}
}

View File

@@ -0,0 +1,8 @@
package kubernetes
// ConfigMap is the key to function docker project source code in configmap
var ConfigMap = struct {
AppMetaEnvName string
}{
AppMetaEnvName: "APP_META",
}

View File

@@ -0,0 +1,103 @@
package kubernetes
import (
"fmt"
"github.com/metrue/fx/types"
appsv1 "k8s.io/api/apps/v1"
apiv1 "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func generateDeploymentSpec(
name string,
image string,
bindPorts []types.PortBinding,
replicas int32,
selector map[string]string,
) *appsv1.Deployment {
ports := []apiv1.ContainerPort{}
for index, binding := range bindPorts {
ports = append(ports, apiv1.ContainerPort{
Name: fmt.Sprintf("fx-container-%d", index),
ContainerPort: binding.ContainerExposePort,
})
}
container := apiv1.Container{
Name: "fx-placeholder-container-name",
Image: image,
Ports: ports,
ImagePullPolicy: v1.PullNever,
}
return &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: selector,
},
Template: apiv1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: selector,
},
Spec: apiv1.PodSpec{
Containers: []apiv1.Container{container},
},
},
},
}
}
// GetDeployment get a deployment
func (k *K8S) GetDeployment(namespace string, name string) (*appsv1.Deployment, error) {
return k.AppsV1().Deployments(namespace).Get(name, metav1.GetOptions{})
}
// CreateDeployment create a deployment
func (k *K8S) CreateDeployment(
namespace string,
name string,
image string,
ports []types.PortBinding,
replicas int32,
selector map[string]string,
) (*appsv1.Deployment, error) {
deployment := generateDeploymentSpec(name, image, ports, replicas, selector)
return k.AppsV1().Deployments(namespace).Create(deployment)
}
// UpdateDeployment update a deployment
func (k *K8S) UpdateDeployment(
namespace string,
name string,
image string,
ports []types.PortBinding,
replicas int32,
selector map[string]string,
) (*appsv1.Deployment, error) {
deployment := generateDeploymentSpec(name, image, ports, replicas, selector)
return k.AppsV1().Deployments(namespace).Update(deployment)
}
// DeleteDeployment delete a deployment
func (k *K8S) DeleteDeployment(namespace string, name string) error {
return k.AppsV1().Deployments(namespace).Delete(name, &metav1.DeleteOptions{})
}
// CreateDeploymentWithInitContainer create a deployment which will wait InitContainer to do the image build before function container start
func (k *K8S) CreateDeploymentWithInitContainer(
namespace string,
name string,
ports []types.PortBinding,
replicas int32,
selector map[string]string,
) (*appsv1.Deployment, error) {
deployment := generateDeploymentSpec(name, name, ports, replicas, selector)
updatedDeployment := injectInitContainer(name, deployment)
fmt.Println(updatedDeployment)
return k.AppsV1().Deployments(namespace).Create(updatedDeployment)
}

View File

@@ -0,0 +1,61 @@
package kubernetes
import (
"os"
"testing"
"github.com/metrue/fx/types"
)
func TestDeployment(t *testing.T) {
namespace := "default"
name := "fx-hello-world"
image := "metrue/kube-hello"
selector := map[string]string{
"app": "fx-app",
}
kubeconfig := os.Getenv("KUBECONFIG")
if kubeconfig == "" {
t.Skip("skip test since no KUBECONFIG given in environment variable")
}
k8s, err := Create()
if err != nil {
t.Fatal(err)
}
if _, err := k8s.GetDeployment(namespace, name); err == nil {
t.Fatalf("should get not found error")
}
replicas := int32(2)
bindings := []types.PortBinding{
types.PortBinding{
ServiceBindingPort: 80,
ContainerExposePort: 3000,
},
types.PortBinding{
ServiceBindingPort: 443,
ContainerExposePort: 3000,
},
}
deployment, err := k8s.CreateDeployment(namespace, name, image, bindings, replicas, selector)
if err != nil {
t.Fatal(err)
}
if deployment == nil {
t.Fatalf("deploymetn should not be %v", nil)
}
if deployment.Name != name {
t.Fatalf("should get %s but got %s", name, deployment.Name)
}
if *deployment.Spec.Replicas != replicas {
t.Fatalf("should get %v but got %v", replicas, deployment.Spec.Replicas)
}
if err := k8s.DeleteDeployment(namespace, name); err != nil {
t.Fatal(err)
}
}

View File

@@ -0,0 +1,5 @@
FROM metrue/fx-node-base
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]

View File

@@ -0,0 +1,9 @@
const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const fx = require('./fx');
const app = new Koa();
app.use(bodyParser());
app.use(fx);
app.listen(3000);

Some files were not shown because too many files have changed in this diff Show More