Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
704a8094e6 | ||
|
|
6f54565195 | ||
|
|
90206fbaa0 | ||
|
|
8fb4aca231 | ||
|
|
70a93a7302 | ||
|
|
c76b6bacc0 | ||
|
|
15bedfb688 | ||
|
|
1447e6949d | ||
|
|
048ab6149a | ||
|
|
8a0abc59db | ||
|
|
039e003af6 | ||
|
|
1ea665386a | ||
|
|
e7c9a67a68 | ||
|
|
afd7f7f436 | ||
|
|
b4300feabc | ||
|
|
a3826046a5 |
+2
-2
@@ -22,7 +22,7 @@ minikube, you'll need to set the proper environment variables with
|
|||||||
|
|
||||||
```
|
```
|
||||||
# Get dependencies
|
# Get dependencies
|
||||||
$ glide install
|
$ glide install -v
|
||||||
|
|
||||||
# Build fission server and an image
|
# Build fission server and an image
|
||||||
$ pushd fission-bundle
|
$ pushd fission-bundle
|
||||||
@@ -41,7 +41,7 @@ minikube and its built-in docker daemon:
|
|||||||
Next, install fission with this image on your kubernetes cluster using the helm chart:
|
Next, install fission with this image on your kubernetes cluster using the helm chart:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ helm install --set "image=minikube/fission-bundle,pullPolicy=IfNotPresent,analytics=false" charts/fission-all
|
$ helm install --set "image=minikube/fission-bundle,imageTag=latest,pullPolicy=IfNotPresent,analytics=false" charts/fission-all
|
||||||
```
|
```
|
||||||
|
|
||||||
And if you're changing the CLI too, you can build it with:
|
And if you're changing the CLI too, you can build it with:
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ defaultContentLanguageInSubdir= true
|
|||||||
editURL = "https://github.com/fission/fission/edit/master/Documentation/docs-site/content/"
|
editURL = "https://github.com/fission/fission/edit/master/Documentation/docs-site/content/"
|
||||||
description = "Documentation for Fission"
|
description = "Documentation for Fission"
|
||||||
author = "Fission"
|
author = "Fission"
|
||||||
showVisitedLinks = true
|
showVisitedLinks = false
|
||||||
themeVariant = "fission"
|
themeVariant = "fission"
|
||||||
|
|
||||||
[outputs]
|
[outputs]
|
||||||
|
|||||||
@@ -7,4 +7,5 @@ weight: 30
|
|||||||
|
|
||||||
# Fission Concepts
|
# Fission Concepts
|
||||||
|
|
||||||
#### Understanding Fission terminology and concepts
|
This is an overview of the few main concepts in Fission: Functions,
|
||||||
|
Environments, and Triggers.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: "Environment"
|
title: "Environments"
|
||||||
draft: false
|
draft: false
|
||||||
weight: 32
|
weight: 32
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -20,19 +20,19 @@ ready. If you already have helm, [skip ahead to the fission install](#install-fi
|
|||||||
Ensure you have the Kubernetes CLI.
|
Ensure you have the Kubernetes CLI.
|
||||||
|
|
||||||
You can get the Kubernetes CLI for OSX like this:
|
You can get the Kubernetes CLI for OSX like this:
|
||||||
```
|
```sh
|
||||||
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin
|
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl && chmod +x kubectl && sudo mv kubectl /usr/local/bin
|
||||||
```
|
```
|
||||||
|
|
||||||
Or, for Linux:
|
Or, for Linux:
|
||||||
```
|
```sh
|
||||||
$ 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 && sudo mv kubectl /usr/local/bin
|
$ 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 && sudo mv kubectl /usr/local/bin
|
||||||
```
|
```
|
||||||
|
|
||||||
Ensure you have access to a cluster; use kubectl to check your
|
Ensure you have access to a cluster; use kubectl to check your
|
||||||
Kubernetes version:
|
Kubernetes version:
|
||||||
|
|
||||||
```
|
```sh
|
||||||
$ kubectl version
|
$ kubectl version
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ the next section](#install-fission).
|
|||||||
First, you'll need the helm CLI:
|
First, you'll need the helm CLI:
|
||||||
|
|
||||||
On __OS X__:
|
On __OS X__:
|
||||||
```
|
```sh
|
||||||
$ curl -LO https://storage.googleapis.com/kubernetes-helm/helm-v2.7.0-darwin-amd64.tar.gz
|
$ curl -LO https://storage.googleapis.com/kubernetes-helm/helm-v2.7.0-darwin-amd64.tar.gz
|
||||||
|
|
||||||
$ tar xzf helm-v2.7.0-darwin-amd64.tar.gz
|
$ tar xzf helm-v2.7.0-darwin-amd64.tar.gz
|
||||||
@@ -56,7 +56,7 @@ $ mv darwin-amd64/helm /usr/local/bin
|
|||||||
```
|
```
|
||||||
|
|
||||||
On __Linux__:
|
On __Linux__:
|
||||||
```
|
```sh
|
||||||
$ curl -LO https://storage.googleapis.com/kubernetes-helm/helm-v2.7.0-linux-amd64.tar.gz
|
$ curl -LO https://storage.googleapis.com/kubernetes-helm/helm-v2.7.0-linux-amd64.tar.gz
|
||||||
|
|
||||||
$ tar xzf helm-v2.7.0-linux-amd64.tar.gz
|
$ tar xzf helm-v2.7.0-linux-amd64.tar.gz
|
||||||
@@ -66,7 +66,7 @@ $ mv linux-amd64/helm /usr/local/bin
|
|||||||
|
|
||||||
Next, install the Helm server on your Kubernetes cluster:
|
Next, install the Helm server on your Kubernetes cluster:
|
||||||
|
|
||||||
```
|
```sh
|
||||||
$ helm init
|
$ helm init
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ $ helm init
|
|||||||
|
|
||||||
#### Minikube
|
#### Minikube
|
||||||
|
|
||||||
```
|
```sh
|
||||||
$ helm install --namespace fission --set serviceType=NodePort https://github.com/fission/fission/releases/download/0.6.0/fission-all-0.6.0.tgz
|
$ helm install --namespace fission --set serviceType=NodePort https://github.com/fission/fission/releases/download/0.6.0/fission-all-0.6.0.tgz
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ want to expose anything outside the cluster.
|
|||||||
|
|
||||||
#### Cloud hosted clusters (GKE, AWS, Azure etc.)
|
#### Cloud hosted clusters (GKE, AWS, Azure etc.)
|
||||||
|
|
||||||
```
|
```sh
|
||||||
$ helm install --namespace fission https://github.com/fission/fission/releases/download/0.6.0/fission-all-0.6.0.tgz
|
$ helm install --namespace fission https://github.com/fission/fission/releases/download/0.6.0/fission-all-0.6.0.tgz
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ The fission-all helm chart installs a full set of services including
|
|||||||
the NATS message queue, influxDB for logs, etc. If you want a more
|
the NATS message queue, influxDB for logs, etc. If you want a more
|
||||||
minimal setup, you can install the fission-core chart instead:
|
minimal setup, you can install the fission-core chart instead:
|
||||||
|
|
||||||
```
|
```sh
|
||||||
$ helm install --namespace fission https://github.com/fission/fission/releases/download/0.6.0/fission-core-0.6.0.tgz
|
$ helm install --namespace fission https://github.com/fission/fission/releases/download/0.6.0/fission-core-0.6.0.tgz
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -104,13 +104,13 @@ $ helm install --namespace fission https://github.com/fission/fission/releases/d
|
|||||||
|
|
||||||
Get the CLI binary for Mac:
|
Get the CLI binary for Mac:
|
||||||
|
|
||||||
```
|
```sh
|
||||||
$ curl -Lo fission https://github.com/fission/fission/releases/download/0.6.0/fission-cli-osx && chmod +x fission && sudo mv fission /usr/local/bin/
|
$ curl -Lo fission https://github.com/fission/fission/releases/download/0.6.0/fission-cli-osx && chmod +x fission && sudo mv fission /usr/local/bin/
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Linux
|
#### Linux
|
||||||
|
|
||||||
```
|
```sh
|
||||||
$ curl -Lo fission https://github.com/fission/fission/releases/download/0.6.0/fission-cli-linux && chmod +x fission && sudo mv fission /usr/local/bin/
|
$ curl -Lo fission https://github.com/fission/fission/releases/download/0.6.0/fission-cli-linux && chmod +x fission && sudo mv fission /usr/local/bin/
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ this windows executable: [fission.exe](https://github.com/fission/fission/releas
|
|||||||
|
|
||||||
Finally, you're ready to use Fission!
|
Finally, you're ready to use Fission!
|
||||||
|
|
||||||
```
|
```sh
|
||||||
$ fission env create --name nodejs --image fission/node-env:0.6.0
|
$ fission env create --name nodejs --image fission/node-env:0.6.0
|
||||||
|
|
||||||
$ curl -LO https://raw.githubusercontent.com/fission/fission/master/examples/nodejs/hello.js
|
$ curl -LO https://raw.githubusercontent.com/fission/fission/master/examples/nodejs/hello.js
|
||||||
|
|||||||
@@ -1,28 +1,38 @@
|
|||||||
---
|
---
|
||||||
title: "Accessing Secret/configmap in function"
|
title: "Accessing Secrets in Functions"
|
||||||
draft: false
|
draft: false
|
||||||
weight: 47
|
weight: 47
|
||||||
---
|
---
|
||||||
|
|
||||||
From fission v0.5.0 and later, functions are able to access [Secrets](https://kubernetes.io/docs/concepts/configuration/secret/) and [ConfigMaps](https://kubernetes.io/docs/concepts/storage/volumes/#configmap) specified by users.
|
Functions can access Kubernetes
|
||||||
|
[Secrets](https://kubernetes.io/docs/concepts/configuration/secret/)
|
||||||
|
and
|
||||||
|
[ConfigMaps](https://kubernetes.io/docs/concepts/storage/volumes/#configmap).
|
||||||
|
|
||||||
### Create Secret and ConfigMap
|
Use secrets for things like API keys, authentication tokens, and so
|
||||||
|
on.
|
||||||
|
|
||||||
You can create Secret and ConfigMap with CLI.
|
Use config maps for any other configuration that doesn't need to be a
|
||||||
|
secret.
|
||||||
|
|
||||||
|
### Create A Secret or a ConfigMap
|
||||||
|
|
||||||
|
You can create a Secret or ConfigMap with the Kubernetes CLI:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
$ kubectl -n default create secret generic foo --from-literal=TEST_KEY="TESTVALUE"
|
$ kubectl -n default create secret generic my-secret --from-literal=TEST_KEY="TESTVALUE"
|
||||||
$ kubectl -n default create configmap bar --from-literal=TEST_KEY=TESTVALUE
|
|
||||||
|
$ kubectl -n default create configmap my-configmap --from-literal=TEST_KEY="TESTVALUE"
|
||||||
```
|
```
|
||||||
|
|
||||||
Or use `kubectl create -f <filename.yaml>` to create these from a YAML file.
|
Or, use `kubectl create -f <filename.yaml>` to create these from a YAML file.
|
||||||
|
|
||||||
``` yaml
|
``` yaml
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
namespace: default
|
namespace: default
|
||||||
name: foo
|
name: my-secret
|
||||||
data:
|
data:
|
||||||
TEST_KEY: VEVTVFZBTFVF # value after base64 encode
|
TEST_KEY: VEVTVFZBTFVF # value after base64 encode
|
||||||
type: Opaque
|
type: Opaque
|
||||||
@@ -32,14 +42,16 @@ apiVersion: v1
|
|||||||
kind: ConfigMap
|
kind: ConfigMap
|
||||||
metadata:
|
metadata:
|
||||||
namespace: default
|
namespace: default
|
||||||
name: bar
|
name: my-configmap
|
||||||
data:
|
data:
|
||||||
TEST_KEY: TESTVALUE
|
TEST_KEY: TESTVALUE
|
||||||
```
|
```
|
||||||
|
|
||||||
### Access Secret and ConfigMap
|
### Accessing Secrets and ConfigMaps
|
||||||
|
|
||||||
Since content of Secret and ConfigMap are key-value pairs, functions can access them with following paths:
|
Secrets and configmaps are accessed similarly. Each secret or
|
||||||
|
configmap is a set of key value pairs. Fission sets these up as files
|
||||||
|
you can read from your function.
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
# Secret path
|
# Secret path
|
||||||
@@ -52,24 +64,25 @@ Since content of Secret and ConfigMap are key-value pairs, functions can access
|
|||||||
From the previous example, the paths are:
|
From the previous example, the paths are:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
# secret foo
|
# secret my-secret
|
||||||
/secrets/default/foo/TEST_KEY
|
/secrets/default/my-secret/TEST_KEY
|
||||||
|
|
||||||
# confimap bar
|
# confimap my-configmap
|
||||||
/configs/default/bar/TEST_KEY
|
/configs/default/my-configmap/TEST_KEY
|
||||||
```
|
```
|
||||||
|
|
||||||
Now, let's create a simple python function (leaker.py) that return value of Secret `foo` and ConfigMap `bar`.
|
Now, let's create a simple python function (leaker.py) that returns
|
||||||
|
the value of Secret `my-secret` and ConfigMap `my-configmap`.
|
||||||
|
|
||||||
``` python
|
``` python
|
||||||
# leaker.py
|
# leaker.py
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
path = "/configs/default/bar/TEST_KEY"
|
path = "/configs/default/my-configmap/TEST_KEY"
|
||||||
f = open(path, "r")
|
f = open(path, "r")
|
||||||
config = f.read()
|
config = f.read()
|
||||||
|
|
||||||
path = "/secrets/default/foo/TEST_KEY"
|
path = "/secrets/default/my-secret/TEST_KEY"
|
||||||
f = open(path, "r")
|
f = open(path, "r")
|
||||||
secret = f.read()
|
secret = f.read()
|
||||||
|
|
||||||
@@ -79,27 +92,29 @@ def main():
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Create environment, function and http trigger.
|
Create an environment and a function:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
# create python env
|
# create python env
|
||||||
$ fission env create --name python --image fission/python-env
|
$ fission env create --name python --image fission/python-env
|
||||||
|
|
||||||
# create function named "leaker"
|
# create function named "leaker"
|
||||||
$ fission fn create --name leaker --env python --code leaker.py --secret foo --configmap bar
|
$ fission fn create --name leaker --env python --code leaker.py --secret my-secret --configmap my-configmap
|
||||||
|
|
||||||
# create route(http trigger)
|
|
||||||
$ fission route create --function leaker --url /leaker --method GET
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Try to access the function, the output should look like following.
|
Run the function, and the output should look like this:
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
$ curl http://$FISSION_ROUTER/leaker
|
$ fission function test --name leaker
|
||||||
ConfigMap: TESTVALUE
|
ConfigMap: TESTVALUE
|
||||||
Secret: TESTVALUE
|
Secret: TESTVALUE
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: If the Secret or ConfigMap value is updated, the function may not get the updated value for some time; it may get a cached older value.
|
|
||||||
|
{{% notice note %}}
|
||||||
|
If the Secret or ConfigMap value is updated, the function may
|
||||||
|
not get the updated value for some time; it may get a cached older
|
||||||
|
value.
|
||||||
|
{{% /notice %}}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ When you create an environment, you can specify a builder image and builder comm
|
|||||||
fission env create --name python --image fission/python-env:latest --builder fission/python-builder:latest
|
fission env create --name python --image fission/python-env:latest --builder fission/python-builder:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
### Viweing environment information
|
### Viewing environment information
|
||||||
|
|
||||||
You can list the environments or view information of an individual environment:
|
You can list the environments or view information of an individual environment:
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: "Trigger"
|
title: "Triggers"
|
||||||
draft: false
|
draft: false
|
||||||
weight: 44
|
weight: 44
|
||||||
---
|
---
|
||||||
@@ -38,11 +38,16 @@ halfhourly 0 30 * * * hello
|
|||||||
minute @every 1m hello
|
minute @every 1m hello
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create a MQ Trigger
|
### Create a Message Queue Trigger
|
||||||
|
|
||||||
For creating a MQ based trigger which will invoke the function when a new message arrives in newfile topic, you can use the syntax below. The response of the function execution will be sent to topic newfileresponse.
|
A message queue trigger invokes a function based on messages from an
|
||||||
|
message queue. Currently, NATS and Azure Storage Queue are supported
|
||||||
|
queues. (Kafka support is under development.)
|
||||||
|
|
||||||
```
|
```
|
||||||
$ fission mqt create --name hellomsg --function hello --mqtype nats-streaming --topic newfile --resptopic newfileresponse
|
$ fission mqt create --name hellomsg --function hello --mqtype nats-streaming --topic newfile --resptopic newfileresponse
|
||||||
trigger 'hellomsg' created
|
trigger 'hellomsg' created
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You can list or update message queue triggers with `fission mqt list`,
|
||||||
|
or `fission mqt update`.
|
||||||
|
|||||||
@@ -40,12 +40,6 @@
|
|||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
{{with ($.Scratch.Get "prevPage")}}
|
|
||||||
<a class="nav nav-prev" href="{{.URL}}" title="{{.Title}}"> <i class="fa fa-chevron-left"></i></a>
|
|
||||||
{{end}}
|
|
||||||
{{with ($.Scratch.Get "nextPage")}}
|
|
||||||
<a class="nav nav-next" href="{{.URL}}" title="{{.Title}}" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ textarea:focus, input[type="email"]:focus, input[type="number"]:focus, input[typ
|
|||||||
box-shadow: inset 0 1px 3px rgba(0,0,0,.06),0 0 5px rgba(0,169,218,.7)
|
box-shadow: inset 0 1px 3px rgba(0,0,0,.06),0 0 5px rgba(0,169,218,.7)
|
||||||
}
|
}
|
||||||
#header-wrapper {
|
#header-wrapper {
|
||||||
|
/*background: #4a4a4b;*/
|
||||||
background: #1E022D;
|
background: #1E022D;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -445,6 +446,7 @@ textarea:focus, input[type="email"]:focus, input[type="number"]:focus, input[typ
|
|||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
font-family: "Work Sans", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
|
font-family: "Work Sans", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
|
||||||
|
/*font-family: -apple-system,BlinkMacSystemFont,"avenir next",avenir,"helvetica neue",helvetica,ubuntu,roboto,noto,"segoe ui",arial,sans-serif;*/
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
font-size: 18px !important;
|
font-size: 18px !important;
|
||||||
@@ -457,11 +459,13 @@ h2, h3, h4, h5, h6 {
|
|||||||
letter-spacing: -1px;
|
letter-spacing: -1px;
|
||||||
}
|
}
|
||||||
h1 {
|
h1 {
|
||||||
font-family: "Novacento Sans Wide", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
|
font-family: "Work Sans", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
|
||||||
text-align: center;
|
/*font-family: "Novacento Sans Wide", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;*/
|
||||||
text-transform: uppercase;
|
/*text-align: center;*/
|
||||||
color: #222;
|
/*text-transform: uppercase;*/
|
||||||
font-weight: 200;
|
color: #5e5e5e;
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: -1px;
|
||||||
}
|
}
|
||||||
blockquote {
|
blockquote {
|
||||||
border-left: 10px solid #F0F2F4;
|
border-left: 10px solid #F0F2F4;
|
||||||
@@ -1116,8 +1120,10 @@ pre .copy-to-clipboard:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#sidebar #shortcuts h3 {
|
#sidebar #shortcuts h3 {
|
||||||
font-family: "Novacento Sans Wide", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
|
/*font-family: "Novacento Sans Wide", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;*/
|
||||||
color: white ;
|
font-family: "Work Sans", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
|
||||||
|
color: #eee;
|
||||||
|
font-weight: 200;
|
||||||
margin-top:1rem;
|
margin-top:1rem;
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -458,8 +458,8 @@ h2, h3, h4, h5, h6 {
|
|||||||
}
|
}
|
||||||
h1 {
|
h1 {
|
||||||
font-family: "Novacento Sans Wide", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
|
font-family: "Novacento Sans Wide", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
|
||||||
text-align: center;
|
/*text-align: center;*/
|
||||||
text-transform: uppercase;
|
/* text-transform: uppercase; */
|
||||||
color: #222;
|
color: #222;
|
||||||
font-weight: 200;
|
font-weight: 200;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -1,2 +1,5 @@
|
|||||||
These instructions are replaced by:
|
These instructions are replaced by:
|
||||||
http://fission.io/docs/0.4.0/installation/
|
|
||||||
|
http://fission.io/docs/0.6.0/installation/
|
||||||
|
|
||||||
|
You can change the release number `0.6.0` from [release page](https://github.com/fission/fission/releases).
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
.DEFAULT_GOAL := build
|
.DEFAULT_GOAL := build
|
||||||
|
|
||||||
IMAGE ?= fission/fission-bundle
|
IMAGE ?= fission/fission-bundle
|
||||||
VERSION ?= 0.3.0
|
VERSION ?= latest
|
||||||
ARCH ?= amd64
|
ARCH ?= amd64
|
||||||
OS ?= linux
|
OS ?= linux
|
||||||
|
|
||||||
@@ -42,5 +42,5 @@ image-push: image
|
|||||||
docker push "$(IMAGE):$(VERSION)"
|
docker push "$(IMAGE):$(VERSION)"
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@rm -rf fission-bundle/fission-bundle
|
@rm -f fission-bundle/fission-bundle
|
||||||
@rm -rf fission/fission
|
@rm -f fission/fission
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/dchest/uniuri"
|
"github.com/dchest/uniuri"
|
||||||
|
|
||||||
|
"github.com/fission/fission"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -68,6 +70,11 @@ func MakeBuilder(sharedVolumePath string) *Builder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (builder *Builder) VersionHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
fmt.Fprintf(w, fission.VersionInfo().String())
|
||||||
|
}
|
||||||
|
|
||||||
func (builder *Builder) Handler(w http.ResponseWriter, r *http.Request) {
|
func (builder *Builder) Handler(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method != "POST" {
|
if r.Method != "POST" {
|
||||||
e := fmt.Sprintf("Method not allowed: %v", r.Method)
|
e := fmt.Sprintf("Method not allowed: %v", r.Method)
|
||||||
|
|||||||
+16
-1
@@ -1,3 +1,18 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -gcflags=-trimpath=$GOPATH -asmflags=-trimpath=$GOPATH -o builder .
|
version=$1
|
||||||
|
if [ -z $version ]; then
|
||||||
|
version=$(git rev-parse HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
date=$2
|
||||||
|
if [ -z $date ]; then
|
||||||
|
date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||||
|
fi
|
||||||
|
|
||||||
|
gitcommit=$3
|
||||||
|
if [ -z $gitcommit ]; then
|
||||||
|
gitcommit=$(git rev-parse HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -gcflags=-trimpath=$GOPATH -asmflags=-trimpath=$GOPATH -ldflags "-X github.com/fission/fission.GitCommit=$gitcommit -X github.com/fission/fission.BuildDate=$date -X github.com/fission/fission.Version=$version" -o builder .
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ func main() {
|
|||||||
builder := builder.MakeBuilder(dir)
|
builder := builder.MakeBuilder(dir)
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.HandleFunc("/", builder.Handler)
|
mux.HandleFunc("/", builder.Handler)
|
||||||
|
mux.HandleFunc("/version", builder.VersionHandler)
|
||||||
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
|
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -497,7 +497,7 @@ func (envw *environmentWatcher) createBuilderDeployment(env *crd.Environment) (*
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Containers: []apiv1.Container{
|
Containers: []apiv1.Container{
|
||||||
{
|
fission.MergeContainerSpecs(&apiv1.Container{
|
||||||
Name: "builder",
|
Name: "builder",
|
||||||
Image: env.Spec.Builder.Image,
|
Image: env.Spec.Builder.Image,
|
||||||
ImagePullPolicy: apiv1.PullAlways,
|
ImagePullPolicy: apiv1.PullAlways,
|
||||||
@@ -530,7 +530,7 @@ func (envw *environmentWatcher) createBuilderDeployment(env *crd.Environment) (*
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
}, env.Spec.Builder.Container),
|
||||||
{
|
{
|
||||||
Name: "fetcher",
|
Name: "fetcher",
|
||||||
Image: envw.fetcherImage,
|
Image: envw.fetcherImage,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
name: fission-all
|
name: fission-all
|
||||||
version: 0.6.0
|
version: 0.6.1
|
||||||
description: Fission is a fast serverless framework for Kubernetes.
|
description: Fission is a fast serverless framework for Kubernetes.
|
||||||
keywords:
|
keywords:
|
||||||
- fission
|
- fission
|
||||||
@@ -12,4 +12,4 @@ maintainers:
|
|||||||
- name: Ta Ching Chen
|
- name: Ta Ching Chen
|
||||||
email: contact@tachingchen.com
|
email: contact@tachingchen.com
|
||||||
engine: gotpl
|
engine: gotpl
|
||||||
appVersion: 0.6.0
|
appVersion: 0.6.1
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
1. Install the client CLI.
|
1. Install the client CLI.
|
||||||
|
|
||||||
Mac:
|
Mac:
|
||||||
$ curl -Lo fission https://github.com/fission/fission/releases/download/0.6.0/fission-cli-osx && chmod +x fission && sudo mv fission /usr/local/bin/
|
$ curl -Lo fission https://github.com/fission/fission/releases/download/0.6.1/fission-cli-osx && chmod +x fission && sudo mv fission /usr/local/bin/
|
||||||
|
|
||||||
Linux:
|
Linux:
|
||||||
$ curl -Lo fission https://github.com/fission/fission/releases/download/0.6.0/fission-cli-linux && chmod +x fission && sudo mv fission /usr/local/bin/
|
$ curl -Lo fission https://github.com/fission/fission/releases/download/0.6.1/fission-cli-linux && chmod +x fission && sudo mv fission /usr/local/bin/
|
||||||
|
|
||||||
Windows:
|
Windows:
|
||||||
For Windows, you can use the linux binary on WSL. Or you can download this windows executable: https://github.com/fission/fission/releases/download/0.6.0/fission-cli-windows.exe
|
For Windows, you can use the linux binary on WSL. Or you can download this windows executable: https://github.com/fission/fission/releases/download/0.6.1/fission-cli-windows.exe
|
||||||
|
|
||||||
2. You're ready to use Fission!
|
2. You're ready to use Fission!
|
||||||
|
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ image: fission/fission-bundle
|
|||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
## Fission image version
|
## Fission image version
|
||||||
imageTag: 0.6.0
|
imageTag: 0.6.1
|
||||||
|
|
||||||
## Fission fetcher repository
|
## Fission fetcher repository
|
||||||
fetcherImage: fission/fetcher
|
fetcherImage: fission/fetcher
|
||||||
|
|
||||||
## Fission fetcher image version
|
## Fission fetcher image version
|
||||||
fetcherImageTag: 0.6.0
|
fetcherImageTag: 0.6.1
|
||||||
|
|
||||||
## Port at which Fission controller service should be exposed
|
## Port at which Fission controller service should be exposed
|
||||||
controllerPort: 31313
|
controllerPort: 31313
|
||||||
@@ -48,7 +48,7 @@ enableIstio: false
|
|||||||
logger:
|
logger:
|
||||||
influxdbAdmin: "admin"
|
influxdbAdmin: "admin"
|
||||||
fluentdImage: fission/fluentd
|
fluentdImage: fission/fluentd
|
||||||
fluentdImageTag: 0.6.0
|
fluentdImageTag: 0.6.1
|
||||||
|
|
||||||
## Type of Queue you would like to use
|
## Type of Queue you would like to use
|
||||||
## currently supports nats-streaming, azure-storage-queue
|
## currently supports nats-streaming, azure-storage-queue
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
name: fission-core
|
name: fission-core
|
||||||
version: 0.6.0
|
version: 0.6.1
|
||||||
description: Fission is a fast serverless framework for Kubernetes.
|
description: Fission is a fast serverless framework for Kubernetes.
|
||||||
keywords:
|
keywords:
|
||||||
- fission
|
- fission
|
||||||
@@ -12,4 +12,4 @@ maintainers:
|
|||||||
- name: Ta Ching Chen
|
- name: Ta Ching Chen
|
||||||
email: contact@tachingchen.com
|
email: contact@tachingchen.com
|
||||||
engine: gotpl
|
engine: gotpl
|
||||||
appVersion: 0.6.0
|
appVersion: 0.6.1
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
1. Install the client CLI.
|
1. Install the client CLI.
|
||||||
|
|
||||||
Mac:
|
Mac:
|
||||||
$ curl -Lo fission https://github.com/fission/fission/releases/download/0.6.0/fission-cli-osx && chmod +x fission && sudo mv fission /usr/local/bin/
|
$ curl -Lo fission https://github.com/fission/fission/releases/download/0.6.1/fission-cli-osx && chmod +x fission && sudo mv fission /usr/local/bin/
|
||||||
|
|
||||||
Linux:
|
Linux:
|
||||||
$ curl -Lo fission https://github.com/fission/fission/releases/download/0.6.0/fission-cli-linux && chmod +x fission && sudo mv fission /usr/local/bin/
|
$ curl -Lo fission https://github.com/fission/fission/releases/download/0.6.1/fission-cli-linux && chmod +x fission && sudo mv fission /usr/local/bin/
|
||||||
|
|
||||||
Windows:
|
Windows:
|
||||||
For Windows, you can use the linux binary on WSL. Or you can download this windows executable: https://github.com/fission/fission/releases/download/0.6.0/fission-cli-windows.exe
|
For Windows, you can use the linux binary on WSL. Or you can download this windows executable: https://github.com/fission/fission/releases/download/0.6.1/fission-cli-windows.exe
|
||||||
|
|
||||||
2. You're ready to use Fission!
|
2. You're ready to use Fission!
|
||||||
|
|
||||||
|
|||||||
@@ -144,14 +144,14 @@ spec:
|
|||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: "/healthz"
|
path: "/healthz"
|
||||||
port: "8888"
|
port: 8888
|
||||||
initialDelaySeconds: 1
|
initialDelaySeconds: 1
|
||||||
periodSeconds: 1
|
periodSeconds: 1
|
||||||
failureThreshold: 30
|
failureThreshold: 30
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: "/healthz"
|
path: "/healthz"
|
||||||
port: "8888"
|
port: 8888
|
||||||
initialDelaySeconds: 35
|
initialDelaySeconds: 35
|
||||||
periodSeconds: 5
|
periodSeconds: 5
|
||||||
serviceAccount: fission-svc
|
serviceAccount: fission-svc
|
||||||
@@ -180,14 +180,14 @@ spec:
|
|||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: "/router-healthz"
|
path: "/router-healthz"
|
||||||
port: "8888"
|
port: 8888
|
||||||
initialDelaySeconds: 1
|
initialDelaySeconds: 1
|
||||||
periodSeconds: 1
|
periodSeconds: 1
|
||||||
failureThreshold: 30
|
failureThreshold: 30
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: "/router-healthz"
|
path: "/router-healthz"
|
||||||
port: "8888"
|
port: 8888
|
||||||
initialDelaySeconds: 35
|
initialDelaySeconds: 35
|
||||||
periodSeconds: 5
|
periodSeconds: 5
|
||||||
serviceAccount: fission-svc
|
serviceAccount: fission-svc
|
||||||
@@ -238,14 +238,14 @@ spec:
|
|||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: "/healthz"
|
path: "/healthz"
|
||||||
port: "8888"
|
port: 8888
|
||||||
initialDelaySeconds: 1
|
initialDelaySeconds: 1
|
||||||
periodSeconds: 1
|
periodSeconds: 1
|
||||||
failureThreshold: 30
|
failureThreshold: 30
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: "/healthz"
|
path: "/healthz"
|
||||||
port: "8888"
|
port: 8888
|
||||||
initialDelaySeconds: 35
|
initialDelaySeconds: 35
|
||||||
periodSeconds: 5
|
periodSeconds: 5
|
||||||
serviceAccount: fission-svc
|
serviceAccount: fission-svc
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ routerServiceType: LoadBalancer
|
|||||||
image: fission/fission-bundle
|
image: fission/fission-bundle
|
||||||
|
|
||||||
## Fission image version
|
## Fission image version
|
||||||
imageTag: 0.6.0
|
imageTag: 0.6.1
|
||||||
|
|
||||||
## Image pull policy
|
## Image pull policy
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
@@ -22,7 +22,7 @@ pullPolicy: IfNotPresent
|
|||||||
fetcherImage: fission/fetcher
|
fetcherImage: fission/fetcher
|
||||||
|
|
||||||
## Fission fetcher image version
|
## Fission fetcher image version
|
||||||
fetcherImageTag: 0.6.0
|
fetcherImageTag: 0.6.1
|
||||||
|
|
||||||
## Port at which Fission controller service should be exposed
|
## Port at which Fission controller service should be exposed
|
||||||
controllerPort: 31313
|
controllerPort: 31313
|
||||||
|
|||||||
@@ -19,10 +19,16 @@ package fission
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/gorilla/handlers"
|
||||||
|
"github.com/imdario/mergo"
|
||||||
|
apiv1 "k8s.io/client-go/pkg/api/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func UrlForFunction(name string) string {
|
func UrlForFunction(name string) string {
|
||||||
@@ -52,3 +58,32 @@ func IsNetworkError(err error) bool {
|
|||||||
func GetFunctionIstioServiceName(fnName, fnNamespace string) string {
|
func GetFunctionIstioServiceName(fnName, fnNamespace string) string {
|
||||||
return fmt.Sprintf("istio-%v-%v", fnName, fnNamespace)
|
return fmt.Sprintf("istio-%v-%v", fnName, fnNamespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LoggingMiddleware(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
requestURI := r.RequestURI
|
||||||
|
if !strings.Contains(requestURI, "healthz") {
|
||||||
|
// Call the next handler, which can be another middleware in the chain, or the final handler.
|
||||||
|
handlers.LoggingHandler(os.Stdout, next).ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeContainerSpecs merges container specs using a predefined order.
|
||||||
|
//
|
||||||
|
// The order of the arguments indicates which spec has precedence (lower index takes precedence over higher indexes).
|
||||||
|
// Slices and maps are merged; other fields are set only if they are a zero value.
|
||||||
|
func MergeContainerSpecs(specs ...*apiv1.Container) apiv1.Container {
|
||||||
|
result := &apiv1.Container{}
|
||||||
|
for _, spec := range specs {
|
||||||
|
if spec == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mergo.Merge(result, spec)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *result
|
||||||
|
}
|
||||||
|
|||||||
+3
-3
@@ -24,7 +24,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gorilla/handlers"
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
@@ -138,7 +137,7 @@ func (api *API) getLogDBConfig(dbType string) logDBConfig {
|
|||||||
|
|
||||||
func (api *API) HomeHandler(w http.ResponseWriter, r *http.Request) {
|
func (api *API) HomeHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
fmt.Fprintf(w, "{\"message\": \"Fission API\", \"version\": \"0.6.0\"}\n")
|
fmt.Fprintf(w, fission.VersionInfo().String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) ApiVersionMismatchHandler(w http.ResponseWriter, r *http.Request) {
|
func (api *API) ApiVersionMismatchHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -209,5 +208,6 @@ func (api *API) Serve(port int) {
|
|||||||
address := fmt.Sprintf(":%v", port)
|
address := fmt.Sprintf(":%v", port)
|
||||||
|
|
||||||
log.WithFields(log.Fields{"port": port}).Info("Server started")
|
log.WithFields(log.Fields{"port": port}).Info("Server started")
|
||||||
log.Fatal(http.ListenAndServe(address, handlers.LoggingHandler(os.Stdout, r)))
|
r.Use(fission.LoggingMiddleware)
|
||||||
|
log.Fatal(http.ListenAndServe(address, r))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -214,11 +215,7 @@ func TestEnvironmentApi(t *testing.T) {
|
|||||||
|
|
||||||
e, err := g.client.EnvironmentGet(m)
|
e, err := g.client.EnvironmentGet(m)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
assert(testEnv.Spec.AllowedFunctionsPerContainer == e.Spec.AllowedFunctionsPerContainer, "env AllowedFunctionsPerContainer should match after reading")
|
assert(reflect.DeepEqual(testEnv.Spec, e.Spec), "env should match after reading")
|
||||||
assert(testEnv.Spec.Poolsize == e.Spec.Poolsize, "env Poolsize should match after reading")
|
|
||||||
assert(testEnv.Spec.Builder == e.Spec.Builder, "env Builder should match after reading")
|
|
||||||
assert(testEnv.Spec.Runtime == e.Spec.Runtime, "env Runtime should match after reading")
|
|
||||||
assert(testEnv.Spec.Version == e.Spec.Version, "env Version should match after reading")
|
|
||||||
|
|
||||||
testEnv.Metadata.ResourceVersion = m.ResourceVersion
|
testEnv.Metadata.ResourceVersion = m.ResourceVersion
|
||||||
testEnv.Spec.Runtime.Image = "another-img"
|
testEnv.Spec.Runtime.Image = "another-img"
|
||||||
@@ -266,9 +263,9 @@ func TestWatchApi(t *testing.T) {
|
|||||||
|
|
||||||
w, err := g.client.WatchGet(m)
|
w, err := g.client.WatchGet(m)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
assert((testWatch.Spec.Namespace == w.Spec.Namespace &&
|
assert(testWatch.Spec.Namespace == w.Spec.Namespace &&
|
||||||
testWatch.Spec.Type == w.Spec.Type &&
|
testWatch.Spec.Type == w.Spec.Type &&
|
||||||
testWatch.Spec.FunctionReference == w.Spec.FunctionReference), "watch should match after reading")
|
testWatch.Spec.FunctionReference == w.Spec.FunctionReference, "watch should match after reading")
|
||||||
|
|
||||||
testWatch.Metadata.Name = "yyy"
|
testWatch.Metadata.Name = "yyy"
|
||||||
m2, err := g.client.WatchCreate(testWatch)
|
m2, err := g.client.WatchCreate(testWatch)
|
||||||
|
|||||||
@@ -1,2 +1,17 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -gcflags=-trimpath=$GOPATH -asmflags=-trimpath=$GOPATH -o fetcher .
|
version=$1
|
||||||
|
if [ -z $version ]; then
|
||||||
|
version=$(git rev-parse HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
date=$2
|
||||||
|
if [ -z $date ]; then
|
||||||
|
date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||||
|
fi
|
||||||
|
|
||||||
|
gitcommit=$3
|
||||||
|
if [ -z $gitcommit ]; then
|
||||||
|
gitcommit=$(git rev-parse HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -gcflags=-trimpath=$GOPATH -asmflags=-trimpath=$GOPATH -ldflags "-X github.com/fission/fission.GitCommit=$gitcommit -X github.com/fission/fission.BuildDate=$date -X github.com/fission/fission.Version=$version" -o fetcher .
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ func main() {
|
|||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.HandleFunc("/", fetcher.FetchHandler)
|
mux.HandleFunc("/", fetcher.FetchHandler)
|
||||||
mux.HandleFunc("/upload", fetcher.UploadHandler)
|
mux.HandleFunc("/upload", fetcher.UploadHandler)
|
||||||
|
mux.HandleFunc("/version", fetcher.VersionHandler)
|
||||||
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
|
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -163,6 +163,11 @@ func writeSecretOrConfigMap(dataMap map[string][]byte, dirPath string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fetcher *Fetcher) VersionHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
|
fmt.Fprintf(w, fission.VersionInfo().String())
|
||||||
|
}
|
||||||
|
|
||||||
func (fetcher *Fetcher) FetchHandler(w http.ResponseWriter, r *http.Request) {
|
func (fetcher *Fetcher) FetchHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method != "POST" {
|
if r.Method != "POST" {
|
||||||
http.Error(w, "only POST is supported on this endpoint", http.StatusMethodNotAllowed)
|
http.Error(w, "only POST is supported on this endpoint", http.StatusMethodNotAllowed)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ spec:
|
|||||||
version: 2
|
version: 2
|
||||||
builder:
|
builder:
|
||||||
command: build
|
command: build
|
||||||
image: fission/go-build-env:latest
|
image: fission/go-builder:0.6.0
|
||||||
runtime:
|
runtime:
|
||||||
image: fission/go-env:latest
|
image: fission/go-env:0.6.0
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -23,10 +23,8 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gorilla/handlers"
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
@@ -113,5 +111,6 @@ func (executor *Executor) Serve(port int) {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
executor.ndm.Run(ctx)
|
executor.ndm.Run(ctx)
|
||||||
log.Fatal(http.ListenAndServe(address, handlers.LoggingHandler(os.Stdout, r)))
|
r.Use(fission.LoggingMiddleware)
|
||||||
|
log.Fatal(http.ListenAndServe(address, r))
|
||||||
}
|
}
|
||||||
|
|||||||
+27
-18
@@ -22,6 +22,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
@@ -117,30 +118,38 @@ func idleObjectReaper(kubeClient *kubernetes.Clientset,
|
|||||||
for _, fsvc := range funcSvcs {
|
for _, fsvc := range funcSvcs {
|
||||||
|
|
||||||
fn, err := fissionClient.Functions(fsvc.Function.Namespace).Get(fsvc.Function.Name)
|
fn, err := fissionClient.Functions(fsvc.Function.Namespace).Get(fsvc.Function.Name)
|
||||||
if err != nil {
|
if err == nil {
|
||||||
|
// Ignore functions of NewDeploy ExecutorType with MinScale > 0
|
||||||
|
if fn.Spec.InvokeStrategy.ExecutionStrategy.MinScale > 0 &&
|
||||||
|
fn.Spec.InvokeStrategy.ExecutionStrategy.ExecutorType == fission.ExecutorTypeNewdeploy {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return errors not equal to "is not found" error
|
||||||
|
if err != nil && !errors.IsNotFound(err) {
|
||||||
log.Printf("Error getting function: %v", fsvc.Function.Name)
|
log.Printf("Error getting function: %v", fsvc.Function.Name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore functions of NewDeploy ExecutorType with MinScale > 0
|
// Newdeploy manager handles the function delete event and clean cache/kubeobjs itself,
|
||||||
if fn.Spec.InvokeStrategy.ExecutionStrategy.MinScale > 0 && fn.Spec.InvokeStrategy.ExecutionStrategy.ExecutorType == fission.ExecutorTypeNewdeploy {
|
// so we ignore the function service cache with newdepoy executor type here.
|
||||||
continue
|
if fsvc.Executor != fscache.NEWDEPLOY {
|
||||||
}
|
deleted, err := fsCache.DeleteOld(fsvc, idlePodReapTime)
|
||||||
deleted, err := fsCache.DeleteOld(fsvc, idlePodReapTime)
|
if err != nil {
|
||||||
|
log.Printf("Error deleting Kubernetes objects for fsvc '%v': %v", fsvc, err)
|
||||||
if err != nil {
|
log.Printf("Object Name| Object Kind | Object Namespace")
|
||||||
log.Printf("Error deleting Kubernetes objects for fsvc '%v': %v", fsvc, err)
|
for _, kubeobj := range fsvc.KubernetesObjects {
|
||||||
log.Printf("Object Name| Object Kind | Object Namespace")
|
log.Printf("%v | %v | %v", kubeobj.Name, kubeobj.Kind, kubeobj.Namespace)
|
||||||
for _, kubeobj := range fsvc.KubernetesObjects {
|
}
|
||||||
log.Printf("%v | %v | %v", kubeobj.Name, kubeobj.Kind, kubeobj.Namespace)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if !deleted {
|
if !deleted {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, kubeobj := range fsvc.KubernetesObjects {
|
for _, kubeobj := range fsvc.KubernetesObjects {
|
||||||
deleteKubeobject(kubeClient, &kubeobj)
|
deleteKubeobject(kubeClient, &kubeobj)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/client-go/pkg/api"
|
"k8s.io/client-go/pkg/api"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
@@ -56,8 +57,9 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
FunctionServiceCache struct {
|
FunctionServiceCache struct {
|
||||||
byFunction *cache.Cache // function-key -> funcSvc : map[string]*funcSvc
|
byFunction *cache.Cache // function-key -> funcSvc : map[string]*funcSvc
|
||||||
byAddress *cache.Cache // address -> function : map[string]metav1.ObjectMeta
|
byAddress *cache.Cache // address -> function : map[string]metav1.ObjectMeta
|
||||||
|
byFunctionUID *cache.Cache // function uid -> function : map[string]metav1.ObjectMeta
|
||||||
|
|
||||||
requestChannel chan *fscRequest
|
requestChannel chan *fscRequest
|
||||||
}
|
}
|
||||||
@@ -76,10 +78,25 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func IsNotFoundError(err error) bool {
|
||||||
|
if fe, ok := err.(fission.Error); ok {
|
||||||
|
return fe.Code == fission.ErrorNotFound
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsNameExistError(err error) bool {
|
||||||
|
if fe, ok := err.(fission.Error); ok {
|
||||||
|
return fe.Code == fission.ErrorNameExists
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func MakeFunctionServiceCache() *FunctionServiceCache {
|
func MakeFunctionServiceCache() *FunctionServiceCache {
|
||||||
fsc := &FunctionServiceCache{
|
fsc := &FunctionServiceCache{
|
||||||
byFunction: cache.MakeCache(0, 0),
|
byFunction: cache.MakeCache(0, 0),
|
||||||
byAddress: cache.MakeCache(0, 0),
|
byAddress: cache.MakeCache(0, 0),
|
||||||
|
byFunctionUID: cache.MakeCache(0, 0),
|
||||||
requestChannel: make(chan *fscRequest),
|
requestChannel: make(chan *fscRequest),
|
||||||
}
|
}
|
||||||
go fsc.service()
|
go fsc.service()
|
||||||
@@ -136,6 +153,27 @@ func (fsc *FunctionServiceCache) GetByFunction(m *metav1.ObjectMeta) (*FuncSvc,
|
|||||||
return &fsvcCopy, nil
|
return &fsvcCopy, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fsc *FunctionServiceCache) GetByFunctionUID(uid types.UID) (*FuncSvc, error) {
|
||||||
|
mI, err := fsc.byFunctionUID.Get(uid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
m := mI.(metav1.ObjectMeta)
|
||||||
|
|
||||||
|
fsvcI, err := fsc.byFunction.Get(crd.CacheKey(&m))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// update atime
|
||||||
|
fsvc := fsvcI.(*FuncSvc)
|
||||||
|
fsvc.Atime = time.Now()
|
||||||
|
|
||||||
|
fsvcCopy := *fsvc
|
||||||
|
return &fsvcCopy, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (fsc *FunctionServiceCache) Add(fsvc FuncSvc) (*FuncSvc, error) {
|
func (fsc *FunctionServiceCache) Add(fsvc FuncSvc) (*FuncSvc, error) {
|
||||||
err, existing := fsc.byFunction.Set(crd.CacheKey(fsvc.Function), &fsvc)
|
err, existing := fsc.byFunction.Set(crd.CacheKey(fsvc.Function), &fsvc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -158,16 +196,28 @@ func (fsc *FunctionServiceCache) Add(fsvc FuncSvc) (*FuncSvc, error) {
|
|||||||
// because of multiple-specialization. See issue #331.
|
// because of multiple-specialization. See issue #331.
|
||||||
err, _ = fsc.byAddress.Set(fsvc.Address, *fsvc.Function)
|
err, _ = fsc.byAddress.Set(fsvc.Address, *fsvc.Function)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if fe, ok := err.(fission.Error); ok {
|
if IsNameExistError(err) {
|
||||||
if fe.Code == fission.ErrorNameExists {
|
err = nil
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error caching fsvc: %v", err)
|
log.Printf("error caching fsvc: %v", err)
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add to byFunctionUID cache. Ignore NameExists errors
|
||||||
|
// because of multiple-specialization. See issue #331.
|
||||||
|
err, _ = fsc.byFunctionUID.Set(fsvc.Function.UID, *fsvc.Function)
|
||||||
|
if err != nil {
|
||||||
|
if IsNameExistError(err) {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("error caching fsvc by function uid: %v", err)
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,6 +254,7 @@ func (fsc *FunctionServiceCache) DeleteOld(fsvc *FuncSvc, minAge time.Duration)
|
|||||||
|
|
||||||
fsc.byFunction.Delete(crd.CacheKey(fsvc.Function))
|
fsc.byFunction.Delete(crd.CacheKey(fsvc.Function))
|
||||||
fsc.byAddress.Delete(fsvc.Address)
|
fsc.byAddress.Delete(fsvc.Address)
|
||||||
|
fsc.byFunctionUID.Delete(fsvc.Function.UID)
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,11 @@ func TestFunctionServiceCache(t *testing.T) {
|
|||||||
fsc.Log()
|
fsc.Log()
|
||||||
log.Panicf("Failed to get fsvc: %v", err)
|
log.Panicf("Failed to get fsvc: %v", err)
|
||||||
}
|
}
|
||||||
|
f, err = fsc.GetByFunctionUID(fsvc.Function.UID)
|
||||||
|
if err != nil {
|
||||||
|
fsc.Log()
|
||||||
|
log.Panicf("Failed to get fsvc by function uid: %v", err)
|
||||||
|
}
|
||||||
fsvc.Atime = f.Atime
|
fsvc.Atime = f.Atime
|
||||||
fsvc.Ctime = f.Ctime
|
fsvc.Ctime = f.Ctime
|
||||||
if f.Address != fsvc.Address {
|
if f.Address != fsvc.Address {
|
||||||
@@ -98,4 +103,10 @@ func TestFunctionServiceCache(t *testing.T) {
|
|||||||
fsc.Log()
|
fsc.Log()
|
||||||
log.Panicf("found fsvc while expecting empty cache: %v", err)
|
log.Panicf("found fsvc while expecting empty cache: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, err = fsc.GetByFunctionUID(fsvc.Function.UID)
|
||||||
|
if err == nil {
|
||||||
|
fsc.Log()
|
||||||
|
log.Panicf("found fsvc by function uid while expecting empty cache: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,10 @@ func (deploy *NewDeploy) createOrGetDeployment(fn *crd.Function, env *crd.Enviro
|
|||||||
}
|
}
|
||||||
|
|
||||||
existingDepl, err := deploy.kubernetesClient.ExtensionsV1beta1().Deployments(deploy.namespace).Get(deployName, metav1.GetOptions{})
|
existingDepl, err := deploy.kubernetesClient.ExtensionsV1beta1().Deployments(deploy.namespace).Get(deployName, metav1.GetOptions{})
|
||||||
if err == nil && existingDepl.Status.ReadyReplicas >= replicas {
|
if err == nil {
|
||||||
|
if existingDepl.Status.ReadyReplicas < replicas {
|
||||||
|
existingDepl, err = deploy.waitForDeploy(existingDepl, replicas)
|
||||||
|
}
|
||||||
return existingDepl, err
|
return existingDepl, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,18 +78,7 @@ func (deploy *NewDeploy) createOrGetDeployment(fn *crd.Function, env *crd.Enviro
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < 120; i++ {
|
return deploy.waitForDeploy(depl, replicas)
|
||||||
latestDepl, err := deploy.kubernetesClient.ExtensionsV1beta1().Deployments(deploy.namespace).Get(depl.Name, metav1.GetOptions{})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
//TODO check for imagePullerror
|
|
||||||
if latestDepl.Status.ReadyReplicas == replicas {
|
|
||||||
return latestDepl, err
|
|
||||||
}
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
}
|
|
||||||
return nil, errors.New("failed to create deployment within timeout window")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -201,7 +193,7 @@ func (deploy *NewDeploy) getDeploymentSpec(fn *crd.Function, env *crd.Environmen
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Containers: []apiv1.Container{
|
Containers: []apiv1.Container{
|
||||||
{
|
fission.MergeContainerSpecs(&apiv1.Container{
|
||||||
Name: fn.Metadata.Name,
|
Name: fn.Metadata.Name,
|
||||||
Image: env.Spec.Runtime.Image,
|
Image: env.Spec.Runtime.Image,
|
||||||
ImagePullPolicy: apiv1.PullIfNotPresent,
|
ImagePullPolicy: apiv1.PullIfNotPresent,
|
||||||
@@ -231,7 +223,7 @@ func (deploy *NewDeploy) getDeploymentSpec(fn *crd.Function, env *crd.Environmen
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Resources: resources,
|
Resources: resources,
|
||||||
},
|
}, env.Spec.Runtime.Container),
|
||||||
{
|
{
|
||||||
Name: "fetcher",
|
Name: "fetcher",
|
||||||
Image: deploy.fetcherImg,
|
Image: deploy.fetcherImg,
|
||||||
@@ -459,3 +451,18 @@ func (deploy *NewDeploy) deleteSvc(ns string, name string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (deploy *NewDeploy) waitForDeploy(depl *v1beta1.Deployment, replicas int32) (*v1beta1.Deployment, error) {
|
||||||
|
for i := 0; i < 120; i++ {
|
||||||
|
latestDepl, err := deploy.kubernetesClient.ExtensionsV1beta1().Deployments(deploy.namespace).Get(depl.Name, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
//TODO check for imagePullerror
|
||||||
|
if latestDepl.Status.ReadyReplicas >= replicas {
|
||||||
|
return latestDepl, err
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
return nil, errors.New("failed to create deployment within timeout window")
|
||||||
|
}
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ type (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
FnCreate requestType = iota
|
FnCreate requestType = iota
|
||||||
|
FnUpdate
|
||||||
FnDelete
|
FnDelete
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -191,11 +192,27 @@ func (deploy *NewDeploy) GetFuncSvc(metadata *metav1.ObjectMeta) (*fscache.FuncS
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fsvc, err := deploy.fsCache.GetByFunctionUID(metadata.UID)
|
||||||
|
|
||||||
|
// If the function service cache exists, means
|
||||||
|
// the kubeObjects of function are created before.
|
||||||
|
// In this case, return cached fsvc.
|
||||||
|
if err == nil {
|
||||||
|
return fsvc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !fscache.IsNotFoundError(err) {
|
||||||
|
log.Printf("error getting function service by uid: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
deploy.requestChannel <- &fnRequest{
|
deploy.requestChannel <- &fnRequest{
|
||||||
fn: fn,
|
fn: fn,
|
||||||
reqType: FnCreate,
|
reqType: FnCreate,
|
||||||
responseChannel: c,
|
responseChannel: c,
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := <-c
|
resp := <-c
|
||||||
if resp.error != nil {
|
if resp.error != nil {
|
||||||
return nil, resp.error
|
return nil, resp.error
|
||||||
@@ -224,6 +241,19 @@ func (deploy *NewDeploy) createFunction(fn *crd.Function) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (deploy *NewDeploy) updateFunction(fn *crd.Function) {
|
||||||
|
c := make(chan *fnResponse)
|
||||||
|
deploy.requestChannel <- &fnRequest{
|
||||||
|
fn: fn,
|
||||||
|
reqType: FnUpdate,
|
||||||
|
responseChannel: c,
|
||||||
|
}
|
||||||
|
resp := <-c
|
||||||
|
if resp.error != nil {
|
||||||
|
log.Printf("Error eager updating function: %v", resp.error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (deploy *NewDeploy) deleteFunction(fn *crd.Function) {
|
func (deploy *NewDeploy) deleteFunction(fn *crd.Function) {
|
||||||
if fn.Spec.InvokeStrategy.ExecutionStrategy.ExecutorType == fission.ExecutorTypeNewdeploy {
|
if fn.Spec.InvokeStrategy.ExecutionStrategy.ExecutorType == fission.ExecutorTypeNewdeploy {
|
||||||
c := make(chan *fnResponse)
|
c := make(chan *fnResponse)
|
||||||
@@ -336,7 +366,7 @@ func (deploy *NewDeploy) fnUpdate(oldFn *crd.Function, newFn *crd.Function) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
changed := false
|
deployChanged := false
|
||||||
|
|
||||||
if oldFn.Spec.InvokeStrategy != newFn.Spec.InvokeStrategy {
|
if oldFn.Spec.InvokeStrategy != newFn.Spec.InvokeStrategy {
|
||||||
|
|
||||||
@@ -366,59 +396,63 @@ func (deploy *NewDeploy) fnUpdate(oldFn *crd.Function, newFn *crd.Function) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hpaChanged := false
|
||||||
|
|
||||||
if newFn.Spec.InvokeStrategy.ExecutionStrategy.MinScale != oldFn.Spec.InvokeStrategy.ExecutionStrategy.MinScale {
|
if newFn.Spec.InvokeStrategy.ExecutionStrategy.MinScale != oldFn.Spec.InvokeStrategy.ExecutionStrategy.MinScale {
|
||||||
replicas := int32(newFn.Spec.InvokeStrategy.ExecutionStrategy.MinScale)
|
replicas := int32(newFn.Spec.InvokeStrategy.ExecutionStrategy.MinScale)
|
||||||
hpa.Spec.MinReplicas = &replicas
|
hpa.Spec.MinReplicas = &replicas
|
||||||
changed = true // Will start deployment update
|
deployChanged = true
|
||||||
|
hpaChanged = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if newFn.Spec.InvokeStrategy.ExecutionStrategy.MaxScale != oldFn.Spec.InvokeStrategy.ExecutionStrategy.MaxScale {
|
if newFn.Spec.InvokeStrategy.ExecutionStrategy.MaxScale != oldFn.Spec.InvokeStrategy.ExecutionStrategy.MaxScale {
|
||||||
hpa.Spec.MaxReplicas = int32(newFn.Spec.InvokeStrategy.ExecutionStrategy.MaxScale)
|
hpa.Spec.MaxReplicas = int32(newFn.Spec.InvokeStrategy.ExecutionStrategy.MaxScale)
|
||||||
|
hpaChanged = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if newFn.Spec.InvokeStrategy.ExecutionStrategy.TargetCPUPercent != oldFn.Spec.InvokeStrategy.ExecutionStrategy.TargetCPUPercent {
|
if newFn.Spec.InvokeStrategy.ExecutionStrategy.TargetCPUPercent != oldFn.Spec.InvokeStrategy.ExecutionStrategy.TargetCPUPercent {
|
||||||
targetCpupercent := int32(newFn.Spec.InvokeStrategy.ExecutionStrategy.TargetCPUPercent)
|
targetCpupercent := int32(newFn.Spec.InvokeStrategy.ExecutionStrategy.TargetCPUPercent)
|
||||||
hpa.Spec.TargetCPUUtilizationPercentage = &targetCpupercent
|
hpa.Spec.TargetCPUUtilizationPercentage = &targetCpupercent
|
||||||
|
hpaChanged = true
|
||||||
}
|
}
|
||||||
|
|
||||||
err = deploy.updateHpa(hpa)
|
if hpaChanged {
|
||||||
if err != nil {
|
err := deploy.updateHpa(hpa)
|
||||||
updateStatus(oldFn, err, "error updating HPA while updating function")
|
if err != nil {
|
||||||
return
|
updateStatus(oldFn, err, "error updating HPA while updating function")
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if oldFn.Spec.Environment != newFn.Spec.Environment {
|
if oldFn.Spec.Environment != newFn.Spec.Environment ||
|
||||||
changed = true
|
oldFn.Spec.Package.PackageRef != newFn.Spec.Package.PackageRef {
|
||||||
}
|
deployChanged = true
|
||||||
|
|
||||||
if oldFn.Spec.Package.PackageRef != newFn.Spec.Package.PackageRef {
|
|
||||||
changed = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If length of slice has changed then no need to check individual elements
|
// If length of slice has changed then no need to check individual elements
|
||||||
if len(oldFn.Spec.Secrets) != len(newFn.Spec.Secrets) {
|
if len(oldFn.Spec.Secrets) != len(newFn.Spec.Secrets) {
|
||||||
changed = true
|
deployChanged = true
|
||||||
} else {
|
} else {
|
||||||
for i, newSecret := range newFn.Spec.Secrets {
|
for i, newSecret := range newFn.Spec.Secrets {
|
||||||
if newSecret != oldFn.Spec.Secrets[i] {
|
if newSecret != oldFn.Spec.Secrets[i] {
|
||||||
changed = true
|
deployChanged = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(oldFn.Spec.ConfigMaps) != len(newFn.Spec.ConfigMaps) {
|
if len(oldFn.Spec.ConfigMaps) != len(newFn.Spec.ConfigMaps) {
|
||||||
changed = true
|
deployChanged = true
|
||||||
} else {
|
} else {
|
||||||
for i, newConfig := range newFn.Spec.ConfigMaps {
|
for i, newConfig := range newFn.Spec.ConfigMaps {
|
||||||
if newConfig != oldFn.Spec.ConfigMaps[i] {
|
if newConfig != oldFn.Spec.ConfigMaps[i] {
|
||||||
changed = true
|
deployChanged = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if changed == true {
|
if deployChanged == true {
|
||||||
env, err := deploy.fissionClient.Environments(newFn.Spec.Environment.Namespace).
|
env, err := deploy.fissionClient.Environments(newFn.Spec.Environment.Namespace).
|
||||||
Get(newFn.Spec.Environment.Name)
|
Get(newFn.Spec.Environment.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -438,7 +472,6 @@ func (deploy *NewDeploy) fnUpdate(oldFn *crd.Function, newFn *crd.Function) {
|
|||||||
updateStatus(oldFn, err, "failed to update deployment while updating function")
|
updateStatus(oldFn, err, "failed to update deployment while updating function")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,6 +534,20 @@ func (deploy *NewDeploy) getDeployLabels(fn *crd.Function, env *crd.Environment)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// updateKubeObjRefRV update the resource version of kubeObjectRef with
|
||||||
|
// given kind and return error if failed to find the reference.
|
||||||
|
func (deploy *NewDeploy) updateKubeObjRefRV(fsvc *fscache.FuncSvc, objKind string, rv string) error {
|
||||||
|
kubeObjs := fsvc.KubernetesObjects
|
||||||
|
for i, obj := range kubeObjs {
|
||||||
|
if obj.Kind == objKind {
|
||||||
|
kubeObjs[i].ResourceVersion = rv
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fsvc.KubernetesObjects = kubeObjs
|
||||||
|
return errors.New(fmt.Sprintf("error finding kubernetes object reference with kind: %v", objKind))
|
||||||
|
}
|
||||||
|
|
||||||
// updateStatus is a function which updates status of update.
|
// updateStatus is a function which updates status of update.
|
||||||
// Current implementation only logs messages, in future it will update function status
|
// Current implementation only logs messages, in future it will update function status
|
||||||
func updateStatus(fn *crd.Function, err error, message string) {
|
func updateStatus(fn *crd.Function, err error, message string) {
|
||||||
|
|||||||
@@ -445,14 +445,15 @@ func (gp *GenericPool) specializePod(pod *apiv1.Pod, metadata *metav1.ObjectMeta
|
|||||||
// Receive response with non-200 http code
|
// Receive response with non-200 http code
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = fission.MakeErrorFromHTTP(resp2)
|
err = fission.MakeErrorFromHTTP(resp2)
|
||||||
// The istio-proxy block all http requests until it's ready
|
|
||||||
// to serve traffic. Retry if istio feature is enabled.
|
|
||||||
if gp.useIstio {
|
|
||||||
retry = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if retry {
|
// The istio-proxy block all http requests until it's ready
|
||||||
|
// to serve traffic. Retry if istio feature is enabled.
|
||||||
|
if gp.useIstio {
|
||||||
|
retry = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if retry && i < maxRetries-1 {
|
||||||
time.Sleep(500 * time.Duration(2*i) * time.Millisecond)
|
time.Sleep(500 * time.Duration(2*i) * time.Millisecond)
|
||||||
log.Printf("Error connecting to pod (%v), retrying", err)
|
log.Printf("Error connecting to pod (%v), retrying", err)
|
||||||
continue
|
continue
|
||||||
@@ -523,7 +524,7 @@ func (gp *GenericPool) createPool() error {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Containers: []apiv1.Container{
|
Containers: []apiv1.Container{
|
||||||
{
|
fission.MergeContainerSpecs(&apiv1.Container{
|
||||||
Name: gp.env.Metadata.Name,
|
Name: gp.env.Metadata.Name,
|
||||||
Image: gp.env.Spec.Runtime.Image,
|
Image: gp.env.Spec.Runtime.Image,
|
||||||
ImagePullPolicy: gp.runtimeImagePullPolicy,
|
ImagePullPolicy: gp.runtimeImagePullPolicy,
|
||||||
@@ -559,7 +560,7 @@ func (gp *GenericPool) createPool() error {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
}, gp.env.Spec.Runtime.Container),
|
||||||
{
|
{
|
||||||
Name: "fetcher",
|
Name: "fetcher",
|
||||||
Image: gp.fetcherImage,
|
Image: gp.fetcherImage,
|
||||||
|
|||||||
+16
-1
@@ -1,2 +1,17 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -gcflags=-trimpath=$GOPATH -asmflags=-trimpath=$GOPATH
|
version=$1
|
||||||
|
if [ -z $version ]; then
|
||||||
|
version=$(git rev-parse HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
date=$2
|
||||||
|
if [ -z $date ]; then
|
||||||
|
date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||||
|
fi
|
||||||
|
|
||||||
|
gitcommit=$3
|
||||||
|
if [ -z $gitcommit ]; then
|
||||||
|
gitcommit=$(git rev-parse HEAD)
|
||||||
|
fi
|
||||||
|
|
||||||
|
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -gcflags=-trimpath=$GOPATH -asmflags=-trimpath=$GOPATH -ldflags "-X github.com/fission/fission.GitCommit=$gitcommit -X github.com/fission/fission.BuildDate=$date -X github.com/fission/fission.Version=$version"
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/docopt/docopt-go"
|
"github.com/docopt/docopt-go"
|
||||||
|
|
||||||
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/buildermgr"
|
"github.com/fission/fission/buildermgr"
|
||||||
"github.com/fission/fission/controller"
|
"github.com/fission/fission/controller"
|
||||||
"github.com/fission/fission/executor"
|
"github.com/fission/fission/executor"
|
||||||
@@ -120,6 +122,7 @@ Usage:
|
|||||||
fission-bundle --builderMgr [--storageSvcUrl=<url>] [--envbuilder-namespace=<namespace>]
|
fission-bundle --builderMgr [--storageSvcUrl=<url>] [--envbuilder-namespace=<namespace>]
|
||||||
fission-bundle --timer [--routerUrl=<url>]
|
fission-bundle --timer [--routerUrl=<url>]
|
||||||
fission-bundle --mqt [--routerUrl=<url>]
|
fission-bundle --mqt [--routerUrl=<url>]
|
||||||
|
fission-bundle --version
|
||||||
Options:
|
Options:
|
||||||
--controllerPort=<port> Port that the controller should listen on.
|
--controllerPort=<port> Port that the controller should listen on.
|
||||||
--routerPort=<port> Port that the router should listen on.
|
--routerPort=<port> Port that the router should listen on.
|
||||||
@@ -135,8 +138,10 @@ Options:
|
|||||||
--timer Start Timer.
|
--timer Start Timer.
|
||||||
--mqt Start message queue trigger.
|
--mqt Start message queue trigger.
|
||||||
--builderMgr Start builder manager.
|
--builderMgr Start builder manager.
|
||||||
|
--version Print version information
|
||||||
`
|
`
|
||||||
arguments, err := docopt.Parse(usage, nil, true, "fission-bundle", false)
|
version := fmt.Sprintf("Fission Bundle Version: %v", fission.VersionInfo().String())
|
||||||
|
arguments, err := docopt.Parse(usage, nil, true, version, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error: %v", err)
|
log.Fatalf("Error: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -510,7 +510,7 @@ func fnUpdate(c *cli.Context) error {
|
|||||||
default:
|
default:
|
||||||
fatal("Executor type must be one of 'poolmgr' or 'newdeploy', defaults to 'poolmgr'")
|
fatal("Executor type must be one of 'poolmgr' or 'newdeploy', defaults to 'poolmgr'")
|
||||||
}
|
}
|
||||||
if c.IsSet("mincpu") || c.IsSet("maxcpu") || c.IsSet("minmemory") || c.IsSet("maxmemory") &&
|
if (c.IsSet("mincpu") || c.IsSet("maxcpu") || c.IsSet("minmemory") || c.IsSet("maxmemory")) &&
|
||||||
fnExecutor == fission.ExecutorTypePoolmgr {
|
fnExecutor == fission.ExecutorTypePoolmgr {
|
||||||
warn("CPU/Memory specified for function with pool manager executor will be ignored in favor of resources specified at environment")
|
warn("CPU/Memory specified for function with pool manager executor will be ignored in favor of resources specified at environment")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
|
"github.com/fission/fission/controller/client"
|
||||||
"github.com/fission/fission/crd"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -57,6 +58,17 @@ func getMethod(method string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkFunctionExistence(fissionClient *client.Client, fnName string) {
|
||||||
|
meta := &metav1.ObjectMeta{
|
||||||
|
Name: fnName,
|
||||||
|
Namespace: metav1.NamespaceDefault,
|
||||||
|
}
|
||||||
|
_, err := fissionClient.FunctionGet(meta)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("function '%v' does not exist, use 'fission function create --name %v ...' to create the function\n", fnName, fnName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func htCreate(c *cli.Context) error {
|
func htCreate(c *cli.Context) error {
|
||||||
client := getClient(c.GlobalString("server"))
|
client := getClient(c.GlobalString("server"))
|
||||||
|
|
||||||
@@ -73,6 +85,8 @@ func htCreate(c *cli.Context) error {
|
|||||||
method = "GET"
|
method = "GET"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkFunctionExistence(client, fnName)
|
||||||
|
|
||||||
// just name triggers by uuid.
|
// just name triggers by uuid.
|
||||||
triggerName := uuid.NewV4().String()
|
triggerName := uuid.NewV4().String()
|
||||||
|
|
||||||
@@ -115,6 +129,8 @@ func htUpdate(c *cli.Context) error {
|
|||||||
fatal("Nothing to update. Use --function to specify a new function.")
|
fatal("Nothing to update. Use --function to specify a new function.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkFunctionExistence(client, newFn)
|
||||||
|
|
||||||
ht, err := client.HTTPTriggerGet(&metav1.ObjectMeta{
|
ht, err := client.HTTPTriggerGet(&metav1.ObjectMeta{
|
||||||
Name: htName,
|
Name: htName,
|
||||||
Namespace: metav1.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
|
|||||||
+31
-1
@@ -17,9 +17,14 @@ limitations under the License.
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
version "github.com/fission/fission"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -41,11 +46,25 @@ func getKubeConfigPath() string {
|
|||||||
return kubeConfig
|
return kubeConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getFissionAPIVersion(apiUrl string) (string, error) {
|
||||||
|
resp, err := http.Get(apiUrl)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strings.TrimRight(string(body), "\n"), nil
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Name = "fission"
|
app.Name = "fission"
|
||||||
app.Usage = "Serverless functions for Kubernetes"
|
app.Usage = "Serverless functions for Kubernetes"
|
||||||
app.Version = "0.6.0"
|
app.Version = version.Version
|
||||||
|
|
||||||
// fetch the FISSION_URL env variable. If not set, port-forward to controller.
|
// fetch the FISSION_URL env variable. If not set, port-forward to controller.
|
||||||
var value string
|
var value string
|
||||||
@@ -60,6 +79,17 @@ func main() {
|
|||||||
value = fissionUrl
|
value = fissionUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cli.VersionPrinter = func(c *cli.Context) {
|
||||||
|
clientVer := version.VersionInfo().String()
|
||||||
|
fmt.Printf("Client Version: %v\n", clientVer)
|
||||||
|
serverVer, err := getFissionAPIVersion(value)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error getting Fission API version: %v", err)
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Server Version: %v", serverVer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
cli.StringFlag{Name: "server", Value: value, Usage: "Fission server URL"},
|
cli.StringFlag{Name: "server", Value: value, Usage: "Fission server URL"},
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+9
-9
@@ -1,5 +1,5 @@
|
|||||||
hash: 03ac7555eb1f5745e82abe42a07828ffcaac3785a77e7f37a596f30db8189e7f
|
hash: 3b15246c5a7ca26271ef45e705c92351c786cfbf8ca1c093026b458e527ceefa
|
||||||
updated: 2018-02-08T22:40:25.586979477-08:00
|
updated: 2018-02-10T19:04:05.240303+01:00
|
||||||
imports:
|
imports:
|
||||||
- name: cloud.google.com/go
|
- name: cloud.google.com/go
|
||||||
version: 3b1ae45394a234c385be014e9a488f2bb6eef821
|
version: 3b1ae45394a234c385be014e9a488f2bb6eef821
|
||||||
@@ -18,7 +18,7 @@ imports:
|
|||||||
- autorest/azure
|
- autorest/azure
|
||||||
- autorest/date
|
- autorest/date
|
||||||
- name: github.com/coreos/etcd
|
- name: github.com/coreos/etcd
|
||||||
version: 6a265731e10a5137b991c1aa3a83ecefdd149d50
|
version: 9c6d93056575da4da94382f473b0ecfcd9c1443b
|
||||||
subpackages:
|
subpackages:
|
||||||
- client
|
- client
|
||||||
- name: github.com/davecgh/go-spew
|
- name: github.com/davecgh/go-spew
|
||||||
@@ -55,7 +55,7 @@ imports:
|
|||||||
- name: github.com/emicklei/go-restful-swagger12
|
- name: github.com/emicklei/go-restful-swagger12
|
||||||
version: dcef7f55730566d41eae5db10e7d6981829720f6
|
version: dcef7f55730566d41eae5db10e7d6981829720f6
|
||||||
- name: github.com/fsnotify/fsnotify
|
- name: github.com/fsnotify/fsnotify
|
||||||
version: 4da3e2cfbabc9f751898f250b49f2439785783a1
|
version: c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9
|
||||||
- name: github.com/ghodss/yaml
|
- name: github.com/ghodss/yaml
|
||||||
version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee
|
version: 73d445a93680fa1a78ae23a5839bad48f32ba1ee
|
||||||
- name: github.com/go-openapi/analysis
|
- name: github.com/go-openapi/analysis
|
||||||
@@ -104,7 +104,7 @@ imports:
|
|||||||
- name: github.com/howeyc/gopass
|
- name: github.com/howeyc/gopass
|
||||||
version: bf9dde6d0d2c004a008c27aaee91170c786f6db8
|
version: bf9dde6d0d2c004a008c27aaee91170c786f6db8
|
||||||
- name: github.com/imdario/mergo
|
- name: github.com/imdario/mergo
|
||||||
version: 6633656539c1639d9d78127b7d47c622b5d7b6dc
|
version: 163f41321a19dd09362d4c63cc2489db2015f1f4
|
||||||
- name: github.com/influxdata/influxdb
|
- name: github.com/influxdata/influxdb
|
||||||
version: b7bb7e8359642b6e071735b50ae41f5eb343fd42
|
version: b7bb7e8359642b6e071735b50ae41f5eb343fd42
|
||||||
subpackages:
|
subpackages:
|
||||||
@@ -133,7 +133,7 @@ imports:
|
|||||||
subpackages:
|
subpackages:
|
||||||
- pb
|
- pb
|
||||||
- name: github.com/nats-io/nats-streaming-server
|
- name: github.com/nats-io/nats-streaming-server
|
||||||
version: 6fdcdfbb2589e68692a68fd5b64b1b7e7c54bf05
|
version: 33414c6f2179201f7fda8743ba89d07184e3fa77
|
||||||
subpackages:
|
subpackages:
|
||||||
- spb
|
- spb
|
||||||
- util
|
- util
|
||||||
@@ -148,7 +148,7 @@ imports:
|
|||||||
subpackages:
|
subpackages:
|
||||||
- xxHash32
|
- xxHash32
|
||||||
- name: github.com/pkg/errors
|
- name: github.com/pkg/errors
|
||||||
version: f15c970de5b76fac0b59abb32d62c17cc7bed265
|
version: 30136e27e2ac8d167177e8a583aa4c3fea5be833
|
||||||
- name: github.com/PuerkitoBio/purell
|
- name: github.com/PuerkitoBio/purell
|
||||||
version: 8a290539e2e8629dbc4e6bad948158f790ec31f4
|
version: 8a290539e2e8629dbc4e6bad948158f790ec31f4
|
||||||
- name: github.com/PuerkitoBio/urlesc
|
- name: github.com/PuerkitoBio/urlesc
|
||||||
@@ -237,7 +237,7 @@ imports:
|
|||||||
- name: k8s.io/api
|
- name: k8s.io/api
|
||||||
version: 4b8fc5be9b77d91bbb6525d18591c43699a2b4e5
|
version: 4b8fc5be9b77d91bbb6525d18591c43699a2b4e5
|
||||||
- name: k8s.io/apiextensions-apiserver
|
- name: k8s.io/apiextensions-apiserver
|
||||||
version: 0965a40c0530e110459750a7fcb9cfa4910fb944
|
version: fcd622fe88a4a6efcb5aea9e94ee87324ac1b036
|
||||||
subpackages:
|
subpackages:
|
||||||
- pkg/apis/apiextensions
|
- pkg/apis/apiextensions
|
||||||
- pkg/apis/apiextensions/v1beta1
|
- pkg/apis/apiextensions/v1beta1
|
||||||
@@ -245,7 +245,7 @@ imports:
|
|||||||
- pkg/client/clientset/clientset/scheme
|
- pkg/client/clientset/clientset/scheme
|
||||||
- pkg/client/clientset/clientset/typed/apiextensions/v1beta1
|
- pkg/client/clientset/clientset/typed/apiextensions/v1beta1
|
||||||
- name: k8s.io/apimachinery
|
- name: k8s.io/apimachinery
|
||||||
version: 80184f5f100c67bfcda6b8a848e0243fe4bc2772
|
version: 8ab5f3d8a330c2e9baaf84e39042db8d49034ae2
|
||||||
subpackages:
|
subpackages:
|
||||||
- pkg/api/equality
|
- pkg/api/equality
|
||||||
- pkg/api/errors
|
- pkg/api/errors
|
||||||
|
|||||||
@@ -58,3 +58,5 @@ import:
|
|||||||
version: ~1.2.1
|
version: ~1.2.1
|
||||||
- package: github.com/davecgh/go-spew
|
- package: github.com/davecgh/go-spew
|
||||||
version: ~1.1.0
|
version: ~1.1.0
|
||||||
|
- package: github.com/imdario/mergo
|
||||||
|
version: ~0.3.2
|
||||||
|
|||||||
+19
-11
@@ -14,28 +14,36 @@ Prerequisites
|
|||||||
|
|
||||||
The ability to build docker images.
|
The ability to build docker images.
|
||||||
|
|
||||||
`docker login`
|
`docker login` with your own username; get this username added to
|
||||||
|
the fission team on dockerhub.
|
||||||
|
|
||||||
|
4. Install changelog generator tool "github_changelog_generator": https://github.com/skywinder/github-changelog-generator
|
||||||
|
|
||||||
|
|
||||||
Update versions
|
Update versions
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
Update the version in the source code, helm charts and docs.
|
Update the version in the helm charts:
|
||||||
|
|
||||||
In the sources, the version is present in both CLI and controller:
|
|
||||||
fission/main.go
|
|
||||||
controller/api.go
|
|
||||||
|
|
||||||
In each charts, the version is in Chart.yaml, values.yaml and
|
In each charts, the version is in Chart.yaml, values.yaml and
|
||||||
templates/NOTES.yaml.
|
templates/NOTES.yaml.
|
||||||
|
|
||||||
Commit your changes, push them, open a PR, merge it.
|
Commit your changes, push them, open a PR, merge it.
|
||||||
|
|
||||||
|
Update doc versions: Docs live at github.com/fission/docs.fission.io
|
||||||
|
|
||||||
|
|
||||||
Make the release
|
Make the release
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
1. cd to the top of the repo and run
|
|
||||||
|
1. cd to the top of the repo, create a branch:
|
||||||
|
|
||||||
|
git checkout -b vX.Y.Z
|
||||||
|
|
||||||
|
Commit & push the version changes.
|
||||||
|
|
||||||
|
2. Run
|
||||||
|
|
||||||
./hack/release.sh <VERSION>
|
./hack/release.sh <VERSION>
|
||||||
|
|
||||||
@@ -44,13 +52,13 @@ Make the release
|
|||||||
|
|
||||||
This will take a while.
|
This will take a while.
|
||||||
|
|
||||||
2. Generate docs, copy to the right place, push to github
|
3. Push docs update to github
|
||||||
|
|
||||||
3. Copy over charts, update helm chart index, push to github
|
4. Copy over charts into charts repo, update helm chart index, push to github
|
||||||
|
|
||||||
4. Manually test an installation, just for a sanity check
|
5. Manually test an installation, just for a sanity check
|
||||||
|
|
||||||
5. Switch the github release from pre-release to release.
|
6. Switch the github release from pre-release to release.
|
||||||
|
|
||||||
|
|
||||||
Update chart repo
|
Update chart repo
|
||||||
|
|||||||
+87
-45
@@ -8,7 +8,7 @@ BUILDDIR=$(realpath $DIR)/build
|
|||||||
|
|
||||||
# Ensure we're on the master branch
|
# Ensure we're on the master branch
|
||||||
check_branch() {
|
check_branch() {
|
||||||
version=$1
|
local version=$1
|
||||||
curr_branch=$(git rev-parse --abbrev-ref HEAD)
|
curr_branch=$(git rev-parse --abbrev-ref HEAD)
|
||||||
if [ $curr_branch != "v${version}" ]
|
if [ $curr_branch != "v${version}" ]
|
||||||
then
|
then
|
||||||
@@ -28,15 +28,22 @@ check_clean() {
|
|||||||
|
|
||||||
# Build CLI binaries for mac/linux/windows
|
# Build CLI binaries for mac/linux/windows
|
||||||
build_all_cli() {
|
build_all_cli() {
|
||||||
build_cli "linux" "linux"
|
local version=$1
|
||||||
build_cli "darwin" "osx"
|
local date=$2
|
||||||
build_cli "windows" "windows"
|
local gitcommit=$3
|
||||||
|
|
||||||
|
build_cli "linux" "linux" $version $date $gitcommit
|
||||||
|
build_cli "darwin" "osx" $version $date $gitcommit
|
||||||
|
build_cli "windows" "windows" $version $date $gitcommit
|
||||||
}
|
}
|
||||||
|
|
||||||
# Build cli binary for one OS, and put it in $BUILDDIR/cli/<os>/
|
# Build cli binary for one OS, and put it in $BUILDDIR/cli/<os>/
|
||||||
build_cli() {
|
build_cli() {
|
||||||
os=$1
|
os=$1
|
||||||
osName=$2
|
osName=$2
|
||||||
|
local version=$3
|
||||||
|
local date=$4
|
||||||
|
local gitcommit=$5
|
||||||
arch="amd64" # parameterize if/when we need to
|
arch="amd64" # parameterize if/when we need to
|
||||||
|
|
||||||
pushd $DIR/fission
|
pushd $DIR/fission
|
||||||
@@ -48,7 +55,7 @@ build_cli() {
|
|||||||
binary=fission-cli-${osName}
|
binary=fission-cli-${osName}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
GOOS=$os GOARCH=$arch go build -gcflags=-trimpath=$GOPATH -asmflags=-trimpath=$GOPATH -o $binary .
|
GOOS=$os GOARCH=$arch go build -gcflags=-trimpath=$GOPATH -asmflags=-trimpath=$GOPATH -ldflags "-X github.com/fission/fission.GitCommit=$gitcommit -X github.com/fission/fission.BuildDate=$date -X github.com/fission/fission.Version=$version" -o $binary .
|
||||||
|
|
||||||
outdir=$BUILDDIR/cli/$osName/
|
outdir=$BUILDDIR/cli/$osName/
|
||||||
mkdir -p $outdir
|
mkdir -p $outdir
|
||||||
@@ -59,12 +66,15 @@ build_cli() {
|
|||||||
|
|
||||||
# Build fission-bundle image
|
# Build fission-bundle image
|
||||||
build_fission_bundle_image() {
|
build_fission_bundle_image() {
|
||||||
version=$1
|
local version=$1
|
||||||
tag=fission/fission-bundle:$version
|
local date=$2
|
||||||
|
local gitcommit=$3
|
||||||
|
|
||||||
|
local tag=fission/fission-bundle:$version
|
||||||
|
|
||||||
pushd $DIR/fission-bundle
|
pushd $DIR/fission-bundle
|
||||||
|
|
||||||
./build.sh
|
./build.sh $version $date $gitcommit
|
||||||
docker build -t $tag .
|
docker build -t $tag .
|
||||||
docker tag $tag fission/fission-bundle:latest
|
docker tag $tag fission/fission-bundle:latest
|
||||||
|
|
||||||
@@ -73,18 +83,20 @@ build_fission_bundle_image() {
|
|||||||
|
|
||||||
# Push fission-bundle image
|
# Push fission-bundle image
|
||||||
push_fission_bundle_image() {
|
push_fission_bundle_image() {
|
||||||
version=$1
|
local version=$1
|
||||||
tag=fission/fission-bundle:$version
|
local tag=fission/fission-bundle:$version
|
||||||
docker push $tag
|
docker push $tag
|
||||||
}
|
}
|
||||||
|
|
||||||
build_fetcher_image() {
|
build_fetcher_image() {
|
||||||
version=$1
|
local version=$1
|
||||||
tag=fission/fetcher:$version
|
local date=$2
|
||||||
|
local gitcommit=$3
|
||||||
|
local tag=fission/fetcher:$version
|
||||||
|
|
||||||
pushd $DIR/environments/fetcher/cmd
|
pushd $DIR/environments/fetcher/cmd
|
||||||
|
|
||||||
./build.sh
|
./build.sh $version $date $gitcommit
|
||||||
docker build -t $tag .
|
docker build -t $tag .
|
||||||
docker tag $tag fission/fetcher:latest
|
docker tag $tag fission/fetcher:latest
|
||||||
|
|
||||||
@@ -92,43 +104,47 @@ build_fetcher_image() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
push_fetcher_image() {
|
push_fetcher_image() {
|
||||||
version=$1
|
local version=$1
|
||||||
tag=fission/fetcher:$version
|
local tag=fission/fetcher:$version
|
||||||
docker push $tag
|
docker push $tag
|
||||||
}
|
}
|
||||||
|
|
||||||
build_builder_image() {
|
build_builder_image() {
|
||||||
version=$1
|
local version=$1
|
||||||
tag=fission/builder:$version
|
local date=$2
|
||||||
|
local gitcommit=$3
|
||||||
|
local tag=fission/builder:$version
|
||||||
|
|
||||||
pushd $DIR/builder/cmd
|
pushd $DIR/builder/cmd
|
||||||
|
|
||||||
./build.sh
|
./build.sh $version $date $gitcommit
|
||||||
docker build -t $tag .
|
docker build -t $tag .
|
||||||
|
docker tag $tag fission/builder:latest
|
||||||
|
|
||||||
popd
|
popd
|
||||||
}
|
}
|
||||||
|
|
||||||
push_builder_image() {
|
push_builder_image() {
|
||||||
version=$1
|
local version=$1
|
||||||
tag=fission/builder:$version
|
local tag=fission/builder:$version
|
||||||
docker push $tag
|
docker push $tag
|
||||||
}
|
}
|
||||||
|
|
||||||
build_logger_image() {
|
build_logger_image() {
|
||||||
version=$1
|
local version=$1
|
||||||
tag=fission/fluentd:$version
|
local tag=fission/fluentd:$version
|
||||||
|
|
||||||
pushd $DIR/logger/fluentd
|
pushd $DIR/logger/fluentd
|
||||||
|
|
||||||
docker build -t $tag .
|
docker build -t $tag .
|
||||||
|
docker tag $tag fission/fluentd:latest
|
||||||
|
|
||||||
popd
|
popd
|
||||||
}
|
}
|
||||||
|
|
||||||
push_logger_image() {
|
push_logger_image() {
|
||||||
version=$1
|
local version=$1
|
||||||
tag=fission/fluentd:$version
|
local tag=fission/fluentd:$version
|
||||||
docker push $tag
|
docker push $tag
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +154,7 @@ build_and_push_logger_image() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
build_and_push_env_image() {
|
build_and_push_env_image() {
|
||||||
version=$1
|
local version=$1
|
||||||
envdir=$2
|
envdir=$2
|
||||||
imgnamebase=$3
|
imgnamebase=$3
|
||||||
imgvariant=$4
|
imgvariant=$4
|
||||||
@@ -169,7 +185,7 @@ build_and_push_env_image() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
build_and_push_all_envs() {
|
build_and_push_all_envs() {
|
||||||
version=$1
|
local version=$1
|
||||||
|
|
||||||
# call with version, env dir, image name base, image name variant
|
# call with version, env dir, image name base, image name variant
|
||||||
build_and_push_env_image "$version" "nodejs" "node-env" ""
|
build_and_push_env_image "$version" "nodejs" "node-env" ""
|
||||||
@@ -186,7 +202,7 @@ build_and_push_all_envs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
build_and_push_env_builder_image() {
|
build_and_push_env_builder_image() {
|
||||||
version=$1
|
local version=$1
|
||||||
envdir=$2
|
envdir=$2
|
||||||
imgnamebase=$3
|
imgnamebase=$3
|
||||||
imgvariant=$4
|
imgvariant=$4
|
||||||
@@ -213,7 +229,7 @@ build_and_push_env_builder_image() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
build_and_push_all_env_builders() {
|
build_and_push_all_env_builders() {
|
||||||
version=$1
|
local version=$1
|
||||||
|
|
||||||
# call with version, env dir, image name base, image name variant
|
# call with version, env dir, image name base, image name variant
|
||||||
build_and_push_env_builder_image "$version" "python" "python-builder" ""
|
build_and_push_env_builder_image "$version" "python" "python-builder" ""
|
||||||
@@ -222,7 +238,7 @@ build_and_push_all_env_builders() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
build_charts() {
|
build_charts() {
|
||||||
version=$1
|
local version=$1
|
||||||
mkdir -p $BUILDDIR/charts
|
mkdir -p $BUILDDIR/charts
|
||||||
pushd $DIR/charts
|
pushd $DIR/charts
|
||||||
find . -iname *.~?~ | xargs rm
|
find . -iname *.~?~ | xargs rm
|
||||||
@@ -235,13 +251,30 @@ build_charts() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
build_all() {
|
build_all() {
|
||||||
version=$1
|
local version=$1
|
||||||
|
|
||||||
if [ -z "$version" ]
|
if [ -z "$version" ]
|
||||||
then
|
then
|
||||||
echo "Version unspecified"
|
echo "Version unspecified"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
local date=$2
|
||||||
|
|
||||||
|
if [ -z "$date" ]
|
||||||
|
then
|
||||||
|
echo "Build date unspecified"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local gitcommit=$3
|
||||||
|
|
||||||
|
if [ -z "gitcommit" ]
|
||||||
|
then
|
||||||
|
echo "Git commit unspecified"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -e $BUILDDIR ]
|
if [ -e $BUILDDIR ]
|
||||||
then
|
then
|
||||||
echo "Removing existing build dir ($BUILDDIR)."
|
echo "Removing existing build dir ($BUILDDIR)."
|
||||||
@@ -250,26 +283,32 @@ build_all() {
|
|||||||
|
|
||||||
mkdir -p $BUILDDIR
|
mkdir -p $BUILDDIR
|
||||||
|
|
||||||
build_fission_bundle_image $version
|
build_fission_bundle_image $version $date $gitcommit
|
||||||
build_fetcher_image $version
|
build_fetcher_image $version $date $gitcommit
|
||||||
build_builder_image $version
|
build_builder_image $version $date $gitcommit
|
||||||
build_logger_image $version
|
build_logger_image $version
|
||||||
build_all_cli
|
build_all_cli $version $date $gitcommit
|
||||||
build_charts $version
|
build_charts $version
|
||||||
}
|
}
|
||||||
|
|
||||||
push_all() {
|
push_all() {
|
||||||
|
local version=$1
|
||||||
push_fission_bundle_image $version
|
push_fission_bundle_image $version
|
||||||
push_fission_bundle_image latest
|
push_fission_bundle_image latest
|
||||||
|
|
||||||
push_fetcher_image $version
|
push_fetcher_image $version
|
||||||
push_fetcher_image latest
|
push_fetcher_image latest
|
||||||
|
|
||||||
push_builder_image $version
|
push_builder_image $version
|
||||||
|
push_builder_image latest
|
||||||
|
|
||||||
push_logger_image $version
|
push_logger_image $version
|
||||||
|
push_logger_image latest
|
||||||
}
|
}
|
||||||
|
|
||||||
tag_and_release() {
|
tag_and_release() {
|
||||||
version=$1
|
local version=$1
|
||||||
gittag=$version
|
local gittag=$version
|
||||||
|
|
||||||
# tag the release
|
# tag the release
|
||||||
git tag $gittag
|
git tag $gittag
|
||||||
@@ -288,8 +327,8 @@ tag_and_release() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
attach_github_release_cli() {
|
attach_github_release_cli() {
|
||||||
version=$1
|
local version=$1
|
||||||
gittag=$version
|
local gittag=$version
|
||||||
# cli
|
# cli
|
||||||
echo "Uploading osx cli"
|
echo "Uploading osx cli"
|
||||||
gothub upload \
|
gothub upload \
|
||||||
@@ -320,8 +359,8 @@ attach_github_release_cli() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
attach_github_release_charts() {
|
attach_github_release_charts() {
|
||||||
version=$1
|
local version=$1
|
||||||
gittag=$version
|
local gittag=$version
|
||||||
|
|
||||||
# helm charts
|
# helm charts
|
||||||
gothub upload \
|
gothub upload \
|
||||||
@@ -343,7 +382,7 @@ attach_github_release_charts() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
generate_changelog() {
|
generate_changelog() {
|
||||||
version=$1
|
local version=$1
|
||||||
|
|
||||||
echo "# ${version}" > new_CHANGELOG.md
|
echo "# ${version}" > new_CHANGELOG.md
|
||||||
echo
|
echo
|
||||||
@@ -364,13 +403,13 @@ generate_changelog() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
create_downloads_table () {
|
create_downloads_table () {
|
||||||
release_tag=$1
|
local release_tag=$1
|
||||||
url_prefix="https://github.com/fission/fission/releases/download"
|
local url_prefix="https://github.com/fission/fission/releases/download"
|
||||||
|
|
||||||
echo "## Downloads for ${version}"
|
echo "## Downloads for ${version}"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
files=$(find build -name '*' -type f)
|
local files=$(find build -name '*' -type f)
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo "filename | sha256 hash"
|
echo "filename | sha256 hash"
|
||||||
@@ -386,10 +425,13 @@ export GITHUB_TOKEN=$(cat ~/.gh-access-token)
|
|||||||
|
|
||||||
|
|
||||||
version=$1
|
version=$1
|
||||||
|
date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
|
||||||
|
gitcommit=$(git rev-parse HEAD)
|
||||||
|
|
||||||
check_branch $version
|
check_branch $version
|
||||||
check_clean
|
check_clean
|
||||||
|
|
||||||
build_all $version
|
build_all $version $date $gitcommit
|
||||||
push_all $version
|
push_all $version
|
||||||
build_and_push_all_envs $version
|
build_and_push_all_envs $version
|
||||||
build_and_push_all_env_builders $version
|
build_and_push_all_env_builders $version
|
||||||
|
|||||||
+120
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 The Fission Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
package fission
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
apiv1 "k8s.io/client-go/pkg/api/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMergeContainerSpecs(t *testing.T) {
|
||||||
|
expected := apiv1.Container{
|
||||||
|
Name: "containerName",
|
||||||
|
Image: "testImage",
|
||||||
|
Command: []string{
|
||||||
|
"command",
|
||||||
|
},
|
||||||
|
Args: []string{
|
||||||
|
"arg1",
|
||||||
|
"arg2",
|
||||||
|
},
|
||||||
|
ImagePullPolicy: apiv1.PullNever,
|
||||||
|
TTY: true,
|
||||||
|
Env: []apiv1.EnvVar{
|
||||||
|
{
|
||||||
|
Name: "a",
|
||||||
|
Value: "b",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "c",
|
||||||
|
Value: "d",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
specs := []*apiv1.Container{
|
||||||
|
{
|
||||||
|
Name: "containerName",
|
||||||
|
Image: "testImage",
|
||||||
|
Command: []string{
|
||||||
|
"command",
|
||||||
|
},
|
||||||
|
Args: []string{
|
||||||
|
"arg1",
|
||||||
|
"arg2",
|
||||||
|
},
|
||||||
|
ImagePullPolicy: apiv1.PullNever,
|
||||||
|
TTY: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "shouldNotBeThere",
|
||||||
|
Image: "shouldNotBeThere",
|
||||||
|
Env: []apiv1.EnvVar{
|
||||||
|
{
|
||||||
|
Name: "a",
|
||||||
|
Value: "b",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ImagePullPolicy: apiv1.PullAlways,
|
||||||
|
TTY: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Env: []apiv1.EnvVar{
|
||||||
|
{
|
||||||
|
Name: "c",
|
||||||
|
Value: "d",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ImagePullPolicy: apiv1.PullIfNotPresent,
|
||||||
|
TTY: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
result := MergeContainerSpecs(specs...)
|
||||||
|
assert.Equal(t, expected, result)
|
||||||
|
|
||||||
|
// Check if merging order actually matters
|
||||||
|
var rspecs []*apiv1.Container
|
||||||
|
for i := len(specs) - 1; i >= 0; i -= 1 {
|
||||||
|
rspecs = append(rspecs, specs[i])
|
||||||
|
}
|
||||||
|
reverseResult := MergeContainerSpecs(rspecs...)
|
||||||
|
assert.NotEqual(t, expected, reverseResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeContainerSpecsSingle(t *testing.T) {
|
||||||
|
expected := apiv1.Container{
|
||||||
|
Name: "containerName",
|
||||||
|
Image: "testImage",
|
||||||
|
Command: []string{
|
||||||
|
"command",
|
||||||
|
},
|
||||||
|
Args: []string{
|
||||||
|
"arg1",
|
||||||
|
"arg2",
|
||||||
|
},
|
||||||
|
ImagePullPolicy: apiv1.PullNever,
|
||||||
|
TTY: true,
|
||||||
|
}
|
||||||
|
result := MergeContainerSpecs(&expected)
|
||||||
|
assert.EqualValues(t, expected, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeContainerSpecsNil(t *testing.T) {
|
||||||
|
expected := apiv1.Container{}
|
||||||
|
result := MergeContainerSpecs()
|
||||||
|
assert.EqualValues(t, expected, result)
|
||||||
|
}
|
||||||
+2
-3
@@ -44,10 +44,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/handlers"
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
@@ -62,6 +60,7 @@ import (
|
|||||||
func router(ctx context.Context, httpTriggerSet *HTTPTriggerSet, resolver *functionReferenceResolver) *mutableRouter {
|
func router(ctx context.Context, httpTriggerSet *HTTPTriggerSet, resolver *functionReferenceResolver) *mutableRouter {
|
||||||
muxRouter := mux.NewRouter()
|
muxRouter := mux.NewRouter()
|
||||||
mr := NewMutableRouter(muxRouter)
|
mr := NewMutableRouter(muxRouter)
|
||||||
|
muxRouter.Use(fission.LoggingMiddleware)
|
||||||
httpTriggerSet.subscribeRouter(ctx, mr, resolver)
|
httpTriggerSet.subscribeRouter(ctx, mr, resolver)
|
||||||
return mr
|
return mr
|
||||||
}
|
}
|
||||||
@@ -69,7 +68,7 @@ func router(ctx context.Context, httpTriggerSet *HTTPTriggerSet, resolver *funct
|
|||||||
func serve(ctx context.Context, port int, httpTriggerSet *HTTPTriggerSet, resolver *functionReferenceResolver) {
|
func serve(ctx context.Context, port int, httpTriggerSet *HTTPTriggerSet, resolver *functionReferenceResolver) {
|
||||||
mr := router(ctx, httpTriggerSet, resolver)
|
mr := router(ctx, httpTriggerSet, resolver)
|
||||||
url := fmt.Sprintf(":%v", port)
|
url := fmt.Sprintf(":%v", port)
|
||||||
http.ListenAndServe(url, handlers.LoggingHandler(os.Stdout, mr))
|
http.ListenAndServe(url, mr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(port int, executorUrl string) {
|
func Start(port int, executorUrl string) {
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/gorilla/handlers"
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
_ "github.com/graymeta/stow/local"
|
_ "github.com/graymeta/stow/local"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@@ -169,7 +168,9 @@ func (ss *StorageService) Start(port int) {
|
|||||||
r.HandleFunc("/healthz", ss.healthHandler).Methods("GET")
|
r.HandleFunc("/healthz", ss.healthHandler).Methods("GET")
|
||||||
|
|
||||||
address := fmt.Sprintf(":%v", port)
|
address := fmt.Sprintf(":%v", port)
|
||||||
log.Fatal(http.ListenAndServe(address, handlers.LoggingHandler(os.Stdout, r)))
|
|
||||||
|
r.Use(fission.LoggingMiddleware)
|
||||||
|
log.Fatal(http.ListenAndServe(address, r))
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunStorageService(storageType StorageType, storagePath string, containerName string, port int, enablePruner bool) *StorageService {
|
func RunStorageService(storageType StorageType, storagePath string, containerName string, port int, enablePruner bool) *StorageService {
|
||||||
|
|||||||
Executable
+11
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
. $(dirname $0)/test_utils.sh
|
||||||
|
|
||||||
|
FILE=$(pwd)/$1
|
||||||
|
|
||||||
|
FAILURES=0
|
||||||
|
run_test ${FILE}
|
||||||
|
exit $FAILURES
|
||||||
+20
-14
@@ -176,7 +176,7 @@ helm_install_fission() {
|
|||||||
helm list -q|xargs -I@ bash -c "helm_uninstall_fission @"
|
helm list -q|xargs -I@ bash -c "helm_uninstall_fission @"
|
||||||
|
|
||||||
# deleting ns does take a while after command is issued
|
# deleting ns does take a while after command is issued
|
||||||
while `kubectl get ns| grep "fission-builder"`
|
while kubectl get ns| grep "fission-builder"
|
||||||
do
|
do
|
||||||
sleep 5
|
sleep 5
|
||||||
done
|
done
|
||||||
@@ -389,28 +389,34 @@ run_all_tests() {
|
|||||||
|
|
||||||
for file in $test_files
|
for file in $test_files
|
||||||
do
|
do
|
||||||
testname=${file#$ROOT/test/tests}
|
run_test ${file}
|
||||||
testpath=$file
|
done
|
||||||
|
}
|
||||||
|
|
||||||
if grep "^#test:disabled" $file
|
run_test() {
|
||||||
|
file=$1
|
||||||
|
|
||||||
|
test_name=${file#${ROOT}/test/tests}
|
||||||
|
test_path=${file}
|
||||||
|
|
||||||
|
if grep "^#test:disabled" ${file}
|
||||||
then
|
then
|
||||||
report_test_skipped $testname
|
report_test_skipped ${test_name}
|
||||||
echo ------- Skipped $testname -------
|
echo ------- Skipped ${test_name} -------
|
||||||
else
|
else
|
||||||
echo ------- Running $testname -------
|
echo ------- Running ${test_name} -------
|
||||||
pushd $(dirname $testpath)
|
pushd $(dirname ${test_path})
|
||||||
if $testpath
|
if ${test_path}
|
||||||
then
|
then
|
||||||
echo SUCCESS: $testname
|
echo [SUCCESS]: ${test_name}
|
||||||
report_test_passed $testname
|
report_test_passed ${test_name}
|
||||||
else
|
else
|
||||||
echo FAILED: $testname
|
echo [FAILED]: ${test_name}
|
||||||
export FAILURES=$(($FAILURES+1))
|
export FAILURES=$(($FAILURES+1))
|
||||||
report_test_failed $testname
|
report_test_failed ${test_name}
|
||||||
fi
|
fi
|
||||||
popd
|
popd
|
||||||
fi
|
fi
|
||||||
done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
install_and_test() {
|
install_and_test() {
|
||||||
|
|||||||
@@ -56,12 +56,19 @@ update_fn() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test_fn() {
|
test_fn() {
|
||||||
log "Doing an HTTP GET on the function's route"
|
echo "Doing an HTTP GET on the function's route"
|
||||||
response0=$(curl http://$FISSION_ROUTER/$1)
|
echo "Checking for valid response"
|
||||||
|
|
||||||
log "Checking for valid response"
|
while true; do
|
||||||
echo $response0 | grep -i $2
|
response0=$(curl http://$FISSION_ROUTER/$1)
|
||||||
|
echo $response0 | grep -i $2
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
}
|
}
|
||||||
|
export -f test_fn
|
||||||
|
|
||||||
# This test only tests one path of execution: updating package and checking results of function
|
# This test only tests one path of execution: updating package and checking results of function
|
||||||
# There might be potential future tests where one can test changes in:
|
# There might be potential future tests where one can test changes in:
|
||||||
@@ -81,10 +88,10 @@ main() {
|
|||||||
create_env $env
|
create_env $env
|
||||||
create_fn $fn_name $env
|
create_fn $fn_name $env
|
||||||
create_route $fn_name
|
create_route $fn_name
|
||||||
test_fn $fn_name "world"
|
timeout 60 bash -c "test_fn $fn_name 'world'"
|
||||||
update_archive
|
update_archive
|
||||||
update_fn $fn_name $env
|
update_fn $fn_name $env
|
||||||
test_fn $fn_name "fission"
|
timeout 60 bash -c "test_fn $fn_name 'fission'"
|
||||||
log "Update function for new deployment executor passed"
|
log "Update function for new deployment executor passed"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Executable
+141
@@ -0,0 +1,141 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# test_env_vars.sh - tests whether a user is able to add environment variables to a Fission environment deployment
|
||||||
|
|
||||||
|
TEST_ID=$(date +%s)
|
||||||
|
ENV=python-${TEST_ID}
|
||||||
|
FN=foo-${TEST_ID}
|
||||||
|
RESOURCE_NS=default # Change to test-specific namespace once we support namespaced CRDs
|
||||||
|
FUNCTION_NS=${FUNCTION_NAMESPACE:-fission-function}
|
||||||
|
BUILDER_NS=fission-builder
|
||||||
|
|
||||||
|
# fs
|
||||||
|
TEST_DIR=/tmp/${TEST_ID}
|
||||||
|
ENV_SPEC_FILE=${TEST_DIR}/${ENV}.yaml
|
||||||
|
FN_FILE=${TEST_DIR}/${FN}.yaml
|
||||||
|
|
||||||
|
log_exec() {
|
||||||
|
cmd=$@
|
||||||
|
echo "> ${cmd}"
|
||||||
|
${cmd}
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
log "Cleaning up..."
|
||||||
|
kubectl -n ${RESOURCE_NS} delete environment/${ENV} || true
|
||||||
|
rm -rf ${TEST_DIR}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup
|
||||||
|
if [ -z "${TEST_NOCLEANUP:-}" ]; then
|
||||||
|
trap cleanup EXIT
|
||||||
|
else
|
||||||
|
log "TEST_NOCLEANUP is set; not cleaning up test artifacts afterwards."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! stat ${TEST_DIR} >/dev/null 2>&1 ; then
|
||||||
|
mkdir ${TEST_DIR}
|
||||||
|
fi
|
||||||
|
|
||||||
|
getPodName() {
|
||||||
|
NS=$1
|
||||||
|
POD=$2
|
||||||
|
kubectl -n ${NS} get po -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' \
|
||||||
|
| grep ${POD} \
|
||||||
|
| head -n 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# retry function adapted from:
|
||||||
|
# https://unix.stackexchange.com/questions/82598/how-do-i-write-a-retry-logic-in-script-to-keep-retrying-to-run-it-upto-5-times/82610
|
||||||
|
function retry {
|
||||||
|
local n=1
|
||||||
|
local max=5
|
||||||
|
local delay=5
|
||||||
|
while true; do
|
||||||
|
"$@" && break || {
|
||||||
|
if [[ ${n} -lt ${max} ]]; then
|
||||||
|
((n++))
|
||||||
|
echo "Command '$@' failed. Attempt $n/$max:"
|
||||||
|
sleep ${delay};
|
||||||
|
else
|
||||||
|
>&2 echo "The command has failed after $n attempts."
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Deploy environment (using kubectl because the Fission cli does not support the container arguments)
|
||||||
|
echo "Writing environment config to $ENV_SPEC_FILE"
|
||||||
|
cat > $ENV_SPEC_FILE <<- EOM
|
||||||
|
apiVersion: fission.io/v1
|
||||||
|
kind: Environment
|
||||||
|
metadata:
|
||||||
|
name: ${ENV}
|
||||||
|
namespace: ${RESOURCE_NS}
|
||||||
|
spec:
|
||||||
|
builder:
|
||||||
|
command: build
|
||||||
|
image: gcr.io/fission-ci/python-env-builder:test
|
||||||
|
container:
|
||||||
|
env:
|
||||||
|
- name: TEST_BUILDER_ENV_KEY
|
||||||
|
value: "TEST_BUILDER_ENV_VAR"
|
||||||
|
|
||||||
|
runtime:
|
||||||
|
image: gcr.io/fission-ci/python-env:test
|
||||||
|
container:
|
||||||
|
env:
|
||||||
|
- name: TEST_RUNTIME_ENV_KEY
|
||||||
|
value: "TEST_RUNTIME_ENV_VAR"
|
||||||
|
version: 2
|
||||||
|
poolsize: 1
|
||||||
|
EOM
|
||||||
|
log_exec kubectl -n ${RESOURCE_NS} apply -f ${ENV_SPEC_FILE}
|
||||||
|
|
||||||
|
sleep 15
|
||||||
|
# Wait for runtime and build env to be deployed
|
||||||
|
retry getPodName ${FUNCTION_NS} ${ENV} | grep '.\+'
|
||||||
|
runtimePod=$(getPodName ${FUNCTION_NS} ${ENV})
|
||||||
|
echo "function pod: ${runtimePod}."
|
||||||
|
retry getPodName ${BUILDER_NS} ${ENV} | grep '.\+'
|
||||||
|
buildPod=$(getPodName ${BUILDER_NS} ${ENV})
|
||||||
|
echo "builder pod: ${buildPod}."
|
||||||
|
|
||||||
|
# Ensure pods are running/ready
|
||||||
|
log "Waiting for ${FUNCTION_NS} ${ENV} to be available..."
|
||||||
|
echo "> kubectl -n ${FUNCTION_NS} exec ${runtimePod} -c ${ENV} env"
|
||||||
|
retry kubectl -n ${FUNCTION_NS} exec ${runtimePod} -c ${ENV} env > /dev/null
|
||||||
|
log "Runtime pod ready."
|
||||||
|
|
||||||
|
log "Waiting for ${BUILDER_NS} ${ENV} to be available..."
|
||||||
|
echo "> kubectl -n ${BUILDER_NS} exec ${buildPod} -c builder env"
|
||||||
|
retry kubectl -n ${BUILDER_NS} exec ${buildPod} -c builder env > /dev/null
|
||||||
|
log "Builder pod ready."
|
||||||
|
|
||||||
|
# Check if the env is set in the runtime
|
||||||
|
status=0
|
||||||
|
if kubectl -n ${FUNCTION_NS} exec ${runtimePod} -c ${ENV} env | grep TEST_RUNTIME_ENV_KEY=TEST_RUNTIME_ENV_VAR ; then
|
||||||
|
log "Runtime env is correct."
|
||||||
|
else
|
||||||
|
log "Runtime does not contain expected env var: TEST_RUNTIME_ENV_KEY=TEST_RUNTIME_ENV_VAR"
|
||||||
|
echo "--- Runtime Env ---"
|
||||||
|
kubectl -n ${FUNCTION_NS} exec ${runtimePod} -c ${ENV} env || true
|
||||||
|
echo "--- End Runtime Env ---"
|
||||||
|
status=5
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if the env is set in the builder
|
||||||
|
if kubectl -n ${BUILDER_NS} exec ${buildPod} -c builder env | grep TEST_BUILDER_ENV_KEY=TEST_BUILDER_ENV_VAR ; then
|
||||||
|
log "Builder env is correct."
|
||||||
|
else
|
||||||
|
log "Builder does not contain expected env var: TEST_BUILDER_ENV_KEY=TEST_BUILDER_ENV_VAR"
|
||||||
|
echo "--- Builder Env ---"
|
||||||
|
kubectl -n ${BUILDER_NS} exec ${buildPod} -c builder env || true
|
||||||
|
echo "--- End Builder Env ---"
|
||||||
|
status=5
|
||||||
|
fi
|
||||||
|
exit ${status}
|
||||||
@@ -42,7 +42,7 @@ done
|
|||||||
|
|
||||||
log "Grabbing logs, should have 4 calls in logs"
|
log "Grabbing logs, should have 4 calls in logs"
|
||||||
|
|
||||||
sleep 15
|
sleep 60
|
||||||
|
|
||||||
fission function logs --name $fn --detail > /tmp/logfile
|
fission function logs --name $fn --detail > /tmp/logfile
|
||||||
|
|
||||||
@@ -61,6 +61,7 @@ log $num logs found
|
|||||||
if [ $num -ne 4 ]
|
if [ $num -ne 4 ]
|
||||||
then
|
then
|
||||||
log "Test Failed: expected 4, found $num logs"
|
log "Test Failed: expected 4, found $num logs"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "All done."
|
log "All done."
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ package fission
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/pkg/api/v1"
|
apiv1 "k8s.io/client-go/pkg/api/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -133,7 +133,7 @@ type (
|
|||||||
ConfigMaps []ConfigMapReference `json:"configmaps"`
|
ConfigMaps []ConfigMapReference `json:"configmaps"`
|
||||||
|
|
||||||
// cpu and memory resources as per K8S standards
|
// cpu and memory resources as per K8S standards
|
||||||
Resources v1.ResourceRequirements `json:"resources"`
|
Resources apiv1.ResourceRequirements `json:"resources"`
|
||||||
|
|
||||||
// InvokeStrategy is a set of controls which affect how function executes
|
// InvokeStrategy is a set of controls which affect how function executes
|
||||||
InvokeStrategy InvokeStrategy
|
InvokeStrategy InvokeStrategy
|
||||||
@@ -208,6 +208,16 @@ type (
|
|||||||
// server listens for function requests. Optional;
|
// server listens for function requests. Optional;
|
||||||
// default 8888.
|
// default 8888.
|
||||||
FunctionEndpointPort int32 `json:"functionendpointport"`
|
FunctionEndpointPort int32 `json:"functionendpointport"`
|
||||||
|
|
||||||
|
// Container allows the modification of the deployed runtime
|
||||||
|
// container using the Kubernetes Container spec. Fission overrides
|
||||||
|
// the following fields:
|
||||||
|
// - Name
|
||||||
|
// - Image; set to the Runtime.Image
|
||||||
|
// - TerminationMessagePath
|
||||||
|
// - ImagePullPolicy
|
||||||
|
// (optional)
|
||||||
|
Container *apiv1.Container `json:"container,omitempty"`
|
||||||
}
|
}
|
||||||
Builder struct {
|
Builder struct {
|
||||||
// Image for containing the language runtime.
|
// Image for containing the language runtime.
|
||||||
@@ -215,6 +225,18 @@ type (
|
|||||||
|
|
||||||
// (Optional) Default build command to run for this build environment.
|
// (Optional) Default build command to run for this build environment.
|
||||||
Command string `json:"command,omitempty"`
|
Command string `json:"command,omitempty"`
|
||||||
|
|
||||||
|
// Container allows the modification of the deployed builder
|
||||||
|
// container using the Kubernetes Container spec. Fission overrides
|
||||||
|
// the following fields:
|
||||||
|
// - Name
|
||||||
|
// - Image; set to the Builder.Image
|
||||||
|
// - Command; set to the Builder.Command
|
||||||
|
// - TerminationMessagePath
|
||||||
|
// - ImagePullPolicy
|
||||||
|
// - ReadinessProbe
|
||||||
|
// (optional)
|
||||||
|
Container *apiv1.Container `json:"container,omitempty"`
|
||||||
}
|
}
|
||||||
EnvironmentSpec struct {
|
EnvironmentSpec struct {
|
||||||
// Environment API version
|
// Environment API version
|
||||||
@@ -237,7 +259,7 @@ type (
|
|||||||
AllowAccessToExternalNetwork bool `json:"allowAccessToExternalNetwork,omitempty"`
|
AllowAccessToExternalNetwork bool `json:"allowAccessToExternalNetwork,omitempty"`
|
||||||
|
|
||||||
// Request and limit resources for the environment
|
// Request and limit resources for the environment
|
||||||
Resources v1.ResourceRequirements `json:"resources"`
|
Resources apiv1.ResourceRequirements `json:"resources"`
|
||||||
|
|
||||||
// The initial pool size for environment
|
// The initial pool size for environment
|
||||||
Poolsize int `json:"poolsize,omitempty"`
|
Poolsize int `json:"poolsize,omitempty"`
|
||||||
|
|||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 The Fission Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package fission
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
GitCommit string // $(git rev-parse HEAD) (1b4716ab84903b2e477135a3dc5afdb07f685cb7)
|
||||||
|
BuildDate string // $(date -u +'%Y-%m-%dT%H:%M:%SZ') (2018-03-08T18:54:38Z)
|
||||||
|
Version string // fission release version (0.6.0)
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Info struct {
|
||||||
|
GitCommit string `json:"GitCommit,omitempty"`
|
||||||
|
BuildDate string `json:"BuildDate,omitempty"`
|
||||||
|
Version string `json:"Version,omitempty"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func VersionInfo() Info {
|
||||||
|
return Info{
|
||||||
|
GitCommit: GitCommit,
|
||||||
|
BuildDate: BuildDate,
|
||||||
|
Version: Version,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (info Info) String() string {
|
||||||
|
v, _ := json.Marshal(info)
|
||||||
|
return string(v)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user