Compare commits
11 Commits
v0.7.0
...
0.7.2-alph
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c12d967ced | ||
|
|
b2a62cbd94 | ||
|
|
536b757602 | ||
|
|
ddff53fff2 | ||
|
|
ae87215cfb | ||
|
|
90d7ec88f0 | ||
|
|
697277e1bb | ||
|
|
a17126c713 | ||
|
|
2c35262b9e | ||
|
|
017a34c13c | ||
|
|
bf8885e91a |
36
.github/workflows/ci.yml
vendored
36
.github/workflows/ci.yml
vendored
@@ -7,7 +7,7 @@ jobs:
|
||||
- name: setup Go 1.12
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
version: 1.12
|
||||
go-version: 1.12
|
||||
id: go
|
||||
|
||||
- name: check out
|
||||
@@ -64,12 +64,28 @@ jobs:
|
||||
DEBUG=true ./build/fx deploy -n hello -p 12345 examples/functions/JavaScript/func.js
|
||||
./build/fx destroy hello
|
||||
rm ${KUBECONFIG}
|
||||
|
||||
# TODO enable when GITHUB fix the localhost network access issue
|
||||
# - name: Unit Test
|
||||
# working-directory:
|
||||
# run: |
|
||||
# docker ps
|
||||
# curl http://127.0.0.1:8866/version
|
||||
# curl http://localhost:8866/version
|
||||
# go test -v ./...
|
||||
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
|
||||
|
||||
117
.github/workflows/release.yml
vendored
Normal file
117
.github/workflows/release.yml
vendored
Normal 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 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
|
||||
34
.github/workflows/releaser.yml
vendored
34
.github/workflows/releaser.yml
vendored
@@ -1,34 +0,0 @@
|
||||
name: releaser
|
||||
|
||||
on:
|
||||
create:
|
||||
tags:
|
||||
- v*.*.*
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
- macOS-latest
|
||||
- windows-latest
|
||||
version:
|
||||
- latest
|
||||
- v0.117.0
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
version: '1.12'
|
||||
- name: GoReleaser
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
uses: goreleaser/goreleaser-action@master
|
||||
with:
|
||||
version: ${{ matrix.version }}
|
||||
args: release --rm-dist
|
||||
@@ -1,6 +1,7 @@
|
||||
run:
|
||||
concurrency: 4
|
||||
deadline: 10m
|
||||
timeout: 10m
|
||||
issues-exit-code: 1
|
||||
tests: true
|
||||
skip-dirs:
|
||||
|
||||
11
README.md
11
README.md
@@ -2,6 +2,7 @@ fx
|
||||
------
|
||||
Poor man's function as a service.
|
||||
<br/>
|
||||

|
||||

|
||||
[](https://codecov.io/gh/metrue/fx)
|
||||
[](https://goreportcard.com/report/github.com/metrue/fx)
|
||||
@@ -32,7 +33,7 @@ Feel free hacking fx to support the languages not listed. Welcome to tweet me [@
|
||||
| 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 | [@mbesancon](https://github.com/mbesancon)| [/examples/Julia](https://github.com/metrue/fx/tree/master/examples/functions/Julia) |
|
||||
| Julia | Supported | [@matbesancon](https://github.com/matbesancon)| [/examples/Julia](https://github.com/metrue/fx/tree/master/examples/functions/Julia) |
|
||||
| D | Supported | [@andre2007](https://github.com/andre2007)| [/examples/D](https://github.com/metrue/fx/tree/master/examples/functions/D) |
|
||||
| R | Working on [need your help](https://github.com/metrue/fx/issues/31) | ||
|
||||
|
||||
@@ -50,13 +51,11 @@ brew install metrue/fx/fx
|
||||
via cURL
|
||||
|
||||
```shell
|
||||
# Install to local directory
|
||||
curl -o- https://raw.githubusercontent.com/metrue/fx/master/scripts/install.sh | bash
|
||||
```
|
||||
|
||||
or Wget
|
||||
|
||||
```shell
|
||||
wget -qO- 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
|
||||
```
|
||||
|
||||
fx will be installed into /usr/local/bin, sometimes you may need `source ~/.zshrc` or `source ~/.bashrc` to make fx available in `$PAHT`.
|
||||
|
||||
67
deploy/kubernetes/deployment.go
Normal file
67
deploy/kubernetes/deployment.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"github.com/metrue/fx/constants"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func generateDeploymentSpec(
|
||||
name string,
|
||||
image string,
|
||||
replicas int32,
|
||||
selector map[string]string,
|
||||
) *appsv1.Deployment {
|
||||
container := apiv1.Container{
|
||||
Name: "fx-placeholder-container-name",
|
||||
Image: image,
|
||||
Ports: []apiv1.ContainerPort{
|
||||
apiv1.ContainerPort{
|
||||
Name: "fx-container",
|
||||
ContainerPort: constants.FxContainerExposePort,
|
||||
},
|
||||
},
|
||||
}
|
||||
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, replicas int32, selector map[string]string) (*appsv1.Deployment, error) {
|
||||
deployment := generateDeploymentSpec(name, image, replicas, selector)
|
||||
return k.AppsV1().Deployments(namespace).Create(deployment)
|
||||
}
|
||||
|
||||
// UpdateDeployment update a deployment
|
||||
func (k *K8S) UpdateDeployment(namespace string, name string, image string, replicas int32, selector map[string]string) (*appsv1.Deployment, error) {
|
||||
deployment := generateDeploymentSpec(name, image, 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{})
|
||||
}
|
||||
49
deploy/kubernetes/dpeloyment_test.go
Normal file
49
deploy/kubernetes/dpeloyment_test.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
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)
|
||||
deployment, err := k8s.CreateDeployment(namespace, name, image, 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)
|
||||
}
|
||||
}
|
||||
@@ -60,16 +60,26 @@ func (k *K8S) Deploy(
|
||||
// By using a label selector between Pod and Service, we can link Service and Pod directly, it means a Endpoint will
|
||||
// be created automatically, then incoming traffic to Service will be forward to Pod.
|
||||
// Then we have no need to create Endpoint manually anymore.
|
||||
labels := map[string]string{
|
||||
"fx-app": "fx-app-" + uuid.New().String(),
|
||||
selector := map[string]string{
|
||||
"app": "fx-app-" + uuid.New().String(),
|
||||
}
|
||||
if _, err := k.CreatePod(
|
||||
namespace,
|
||||
name,
|
||||
image,
|
||||
labels,
|
||||
); err != nil {
|
||||
return err
|
||||
|
||||
const replicas = int32(3)
|
||||
if _, err := k.GetDeployment(namespace, name); err != nil {
|
||||
// TODO enable passing replica from fx CLI
|
||||
if _, err := k.CreateDeployment(
|
||||
namespace,
|
||||
name,
|
||||
image,
|
||||
replicas,
|
||||
selector,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if _, err := k.UpdateDeployment(namespace, name, image, replicas, selector); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO fx should be able to know what's the target Kubernetes service platform
|
||||
@@ -79,14 +89,27 @@ func (k *K8S) Deploy(
|
||||
if !isOnPublicCloud {
|
||||
typ = "NodePort"
|
||||
}
|
||||
if _, err := k.CreateService(
|
||||
namespace,
|
||||
name,
|
||||
typ,
|
||||
ports,
|
||||
labels,
|
||||
); err != nil {
|
||||
return err
|
||||
|
||||
if _, err := k.GetService(namespace, name); err != nil {
|
||||
if _, err := k.CreateService(
|
||||
namespace,
|
||||
name,
|
||||
typ,
|
||||
ports,
|
||||
selector,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if _, err := k.UpdateService(
|
||||
namespace,
|
||||
name,
|
||||
typ,
|
||||
ports,
|
||||
selector,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -102,7 +125,7 @@ func (k *K8S) Destroy(ctx context.Context, name string) error {
|
||||
if err := k.DeleteService(namespace, name); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := k.DeletePod(namespace, name); err != nil {
|
||||
if err := k.DeleteDeployment(namespace, name); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -1,56 +1,67 @@
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/metrue/fx/constants"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
intstr "k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
||||
func generateServiceSpec(
|
||||
namespace string,
|
||||
name string,
|
||||
typ string,
|
||||
ports []int32,
|
||||
selector map[string]string,
|
||||
) *apiv1.Service {
|
||||
servicePorts := []apiv1.ServicePort{
|
||||
apiv1.ServicePort{
|
||||
Name: "http",
|
||||
Protocol: apiv1.ProtocolTCP,
|
||||
Port: 80,
|
||||
TargetPort: intstr.FromInt(int(constants.FxContainerExposePort)),
|
||||
},
|
||||
apiv1.ServicePort{
|
||||
Name: "https",
|
||||
Protocol: apiv1.ProtocolTCP,
|
||||
Port: 443,
|
||||
TargetPort: intstr.FromInt(int(constants.FxContainerExposePort)),
|
||||
},
|
||||
}
|
||||
// Append custom Port
|
||||
for index, port := range ports {
|
||||
servicePorts = append(servicePorts, apiv1.ServicePort{
|
||||
Name: "custom-port-" + strconv.Itoa(index),
|
||||
Protocol: apiv1.ProtocolTCP,
|
||||
Port: port,
|
||||
TargetPort: intstr.FromInt(int(3000)),
|
||||
})
|
||||
}
|
||||
|
||||
return &apiv1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
ClusterName: namespace,
|
||||
},
|
||||
Spec: apiv1.ServiceSpec{
|
||||
Ports: servicePorts,
|
||||
Type: apiv1.ServiceType(typ),
|
||||
Selector: selector,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// CreateService create a service
|
||||
func (k *K8S) CreateService(
|
||||
namespace string,
|
||||
name string,
|
||||
typ string,
|
||||
ports []int32,
|
||||
podsLabels map[string]string,
|
||||
) (*v1.Service, error) {
|
||||
servicePorts := []v1.ServicePort{
|
||||
v1.ServicePort{
|
||||
Name: "http",
|
||||
Protocol: v1.ProtocolTCP,
|
||||
Port: 80,
|
||||
TargetPort: intstr.FromInt(int(constants.FxContainerExposePort)),
|
||||
},
|
||||
v1.ServicePort{
|
||||
Name: "https",
|
||||
Protocol: v1.ProtocolTCP,
|
||||
Port: 443,
|
||||
TargetPort: intstr.FromInt(int(constants.FxContainerExposePort)),
|
||||
},
|
||||
}
|
||||
// Append custom Port
|
||||
for _, port := range ports {
|
||||
servicePorts = append(servicePorts, v1.ServicePort{
|
||||
Name: "custom",
|
||||
Protocol: v1.ProtocolTCP,
|
||||
Port: port,
|
||||
TargetPort: intstr.FromInt(int(3000)),
|
||||
})
|
||||
}
|
||||
|
||||
service := &v1.Service{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
ClusterName: namespace,
|
||||
},
|
||||
Spec: v1.ServiceSpec{
|
||||
Ports: servicePorts,
|
||||
Type: v1.ServiceType(typ),
|
||||
Selector: podsLabels,
|
||||
},
|
||||
}
|
||||
|
||||
selector map[string]string,
|
||||
) (*apiv1.Service, error) {
|
||||
service := generateServiceSpec(namespace, name, typ, ports, selector)
|
||||
createdService, err := k.CoreV1().Services(namespace).Create(service)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -59,9 +70,32 @@ func (k *K8S) CreateService(
|
||||
return createdService, nil
|
||||
}
|
||||
|
||||
// UpdateService update a service
|
||||
// TODO this method is not perfect yet, should refactor later
|
||||
func (k *K8S) UpdateService(
|
||||
namespace string,
|
||||
name string,
|
||||
typ string,
|
||||
ports []int32,
|
||||
selector map[string]string,
|
||||
) (*apiv1.Service, error) {
|
||||
svc, err := k.GetService(namespace, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
svc.Spec.Selector = selector
|
||||
svc.Spec.Type = apiv1.ServiceType(typ)
|
||||
return k.CoreV1().Services(namespace).Update(svc)
|
||||
}
|
||||
|
||||
// DeleteService a service
|
||||
func (k *K8S) DeleteService(namespace string, name string) error {
|
||||
// TODO figure out the elegant way to delete a service
|
||||
options := &metav1.DeleteOptions{}
|
||||
return k.CoreV1().Services(namespace).Delete(name, options)
|
||||
}
|
||||
|
||||
// GetService get a service
|
||||
func (k *K8S) GetService(namespace string, name string) (*apiv1.Service, error) {
|
||||
return k.CoreV1().Services(namespace).Get(name, metav1.GetOptions{})
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package kubernetes
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -49,6 +50,10 @@ func TestK8S(t *testing.T) {
|
||||
}
|
||||
|
||||
serviceName := podName + "-svc"
|
||||
if _, err := k8s.GetService(namespace, serviceName); err == nil {
|
||||
t.Fatalf("should get no service name %s", serviceName)
|
||||
}
|
||||
|
||||
svc, err := k8s.CreateService(namespace, serviceName, "NodePort", ports, labels)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -56,6 +61,26 @@ func TestK8S(t *testing.T) {
|
||||
if svc.Name != serviceName {
|
||||
t.Fatalf("should get %s but got %s", serviceName, svc.Name)
|
||||
}
|
||||
svc, err = k8s.GetService(namespace, serviceName)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if svc.Name != serviceName {
|
||||
t.Fatalf("should get %s but got %v", serviceName, svc.Name)
|
||||
}
|
||||
|
||||
selector := map[string]string{"hello": "world"}
|
||||
svc, err = k8s.UpdateService(namespace, serviceName, "NodePort", ports, selector)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if svc.Name != serviceName {
|
||||
t.Fatalf("should get %s but got %v", serviceName, svc.Name)
|
||||
}
|
||||
if !reflect.DeepEqual(svc.Spec.Selector, selector) {
|
||||
t.Fatalf("should get %v but got %v", selector, svc.Spec.Selector)
|
||||
}
|
||||
|
||||
// TODO check service status
|
||||
if err := k8s.DeleteService(namespace, serviceName); err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
2
fx.go
2
fx.go
@@ -27,7 +27,7 @@ func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "fx"
|
||||
app.Usage = "makes function as a service"
|
||||
app.Version = "0.6.2"
|
||||
app.Version = "0.7.2"
|
||||
|
||||
app.Commands = []cli.Command{
|
||||
{
|
||||
|
||||
@@ -1,41 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
fx_has() {
|
||||
set -e
|
||||
|
||||
has() {
|
||||
type "$1" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
get_package_url() {
|
||||
label=""
|
||||
platform=""
|
||||
if [ "$(uname)" == "Darwin" ]; then
|
||||
label="macOS"
|
||||
platform="macOS"
|
||||
elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
|
||||
label="Tux"
|
||||
platform="Tux"
|
||||
elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then
|
||||
label="windows"
|
||||
platform="windows"
|
||||
elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then
|
||||
label="windows"
|
||||
platform="windows"
|
||||
fi
|
||||
|
||||
curl -s https://api.github.com/repos/metrue/fx/releases/latest | grep browser_download_url | awk -F'"' '{print $4}' | grep ${label}
|
||||
curl https://api.github.com/repos/metrue/fx/releases/latest | grep browser_download_url | awk -F'"' '{print $4}' | grep ${platform}
|
||||
}
|
||||
|
||||
download_and_install() {
|
||||
local url=$1
|
||||
# TODO we can do it on one line
|
||||
rm -rf fx.tar.gz
|
||||
curl -o fx.tar.gz -L -O ${url} && tar -xvzf ./fx.tar.gz --exclude=*.md -C /usr/local/bin
|
||||
rm -rf ./fx.tar.gz
|
||||
url=$(get_package_url)
|
||||
tarFile="fx.tar.gz"
|
||||
targetFile=$(pwd)
|
||||
|
||||
userid=$(id -u)
|
||||
if [ "$userid" != "0" ]; then
|
||||
tarFile="$(pwd)/${tarFile}"
|
||||
else
|
||||
tarFile="/tmp/${tarFile}"
|
||||
targetFile="/usr/local/bin"
|
||||
fi
|
||||
|
||||
if [ -e $tarFile ]; then
|
||||
rm -rf $tarFile
|
||||
fi
|
||||
|
||||
echo "Downloading fx from $url"
|
||||
curl -sSLf $url --output $tarFile
|
||||
if [ "$?" == "0" ]; then
|
||||
echo "Download complete, saved to $tarFile"
|
||||
fi
|
||||
|
||||
echo "Installing fx to ${targetFile}"
|
||||
tar -xvzf ${tarFile} --exclude=*.md -C ${targetFile}
|
||||
echo "fx installed successfully at ${targetFile}"
|
||||
${targetFile}/fx -v
|
||||
|
||||
echo "Cleaning up ${tarFile}"
|
||||
rm -rf ${tarFile}
|
||||
}
|
||||
|
||||
main() {
|
||||
if fx_has "docker"; then
|
||||
url=$(get_package_url)
|
||||
if [ ${url}"X" != "X" ];then
|
||||
download_and_install ${url}
|
||||
fi
|
||||
if has "curl";then
|
||||
download_and_install
|
||||
else
|
||||
echo "No Docker found on this host"
|
||||
echo " - Docker installation: https://docs.docker.com/engine/installation"
|
||||
echo "You need cURL to use this script"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ docker stop fx-agent || true && docker rm fx-agent || true
|
||||
|
||||
$fx infra activate localhost
|
||||
port=20000
|
||||
for lang in 'js' 'rb' 'py' 'go' 'php' 'jl' 'java' 'd'; do
|
||||
for lang in 'js' 'rb' 'py' 'go' 'php' 'java' 'd'; do
|
||||
run $lang $port
|
||||
((port++))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user