Compare commits

...
16 Commits
Author SHA1 Message Date
Soam Vasani 8a097abf9b Chart version update 2017-11-15 13:25:28 -08:00
Soam Vasani 6d0ebfd881 update version to 0.4.0 in docs 2017-11-15 13:18:50 -08:00
Soam Vasani 310183a944 update version to 0.4.0 2017-11-15 13:18:22 -08:00
Soam Vasani 8fc3479428 only set nodeports when servicetype == nodeport 2017-11-15 13:18:22 -08:00
Josh KellyandSoam Vasani b2883a30de Added AWS to install cloud setup (#392)
Add AWS instructions to setup commands, since AWS only provides service hostname, not IP.
2017-11-15 12:49:19 -08:00
prithvirameshandSoam Vasani 8b40ad0b33 Refactor logging to remove logger, use fluentd with kubernetes filter (#380)
Remove the `logger` container from the logging daemonset. 

Remove the outgoing call from the poolmgr to the logger.  Use Fluentd's Kubernetes filter to add function name and UID to influx metadata.  

This means fluentd now figures out when to start collecting function logs on its own, without being informed by poolmgr.  This is great for other execution strategies, and for autoscaling, where fission isn't in direct control of function pod creation.

Also adds an integration test to make sure logging keeps working.
2017-11-14 18:08:57 -08:00
svicenteruizandSoam Vasani 74e05ba3a1 created weather.js in node.js examples, modified README.md (#394) 2017-11-14 15:33:41 -08:00
Cody HillandSoam Vasani e77a3946d7 Added python example to demonstrate status codes. (#395) 2017-11-14 05:51:37 -08:00
Soam Vasani bcf04b1a6c Build both python 3.5 and 2.7 images from the same env 2017-11-09 14:01:02 -08:00
Soam Vasani d8844ab13c release script: use helm package to create charts 2017-11-09 13:38:01 -08:00
Soam Vasani 2e63787b96 rename readme to format markdown 2017-11-09 08:12:47 -08:00
Soam Vasani de19a42b8b multifile example 2017-11-09 08:11:02 -08:00
Ta-Ching ChenandSoam Vasani da07b35a96 Use common controller/store for httpTriggerSet and functionReferenceResolver (#390)
This fixes a bug where functionReferenceResolver returned out-of-date function metadata and caused the router to proxy requests to old function pods.

It also uses the go context package to shutdown the controller when the router is shutting down.
2017-11-09 07:07:14 -08:00
Ta-Ching ChenandSoam Vasani 9694ba4fd1 Delete failed helm releases to prevent test case failure (#393) 2017-11-09 06:04:06 -08:00
Soam Vasani 3644760f19 hugo config 2017-11-08 17:15:54 -08:00
Soam Vasani b89576ff7d chart version update 2017-11-08 15:51:23 -08:00
45 changed files with 413 additions and 451 deletions
+1
View File
@@ -1,3 +1,4 @@
baseURL = "http://fission.io/docs/0.3.0" baseURL = "http://fission.io/docs/0.3.0"
languageCode = "en-us" languageCode = "en-us"
title = "Fission: Serverless Functions for Kubernetes" title = "Fission: Serverless Functions for Kubernetes"
theme = "docdock"
+20 -22
View File
@@ -6,7 +6,7 @@ draft: false
Welcome! This guide will get you up and running with Fission on a Welcome! This guide will get you up and running with Fission on a
Kubernetes cluster. Kubernetes cluster.
### Cluster preliminaries ### Cluster preliminaries
If you don't have a Kubernetes cluster, [here's a quick guide to set If you don't have a Kubernetes cluster, [here's a quick guide to set
@@ -48,18 +48,18 @@ First, you'll need the helm CLI:
On __OS X__: On __OS X__:
``` ```
$ curl -LO https://storage.googleapis.com/kubernetes-helm/helm-v2.6.1-darwin-amd64.tar.gz $ curl -LO https://storage.googleapis.com/kubernetes-helm/helm-v2.7.0-darwin-amd64.tar.gz
$ tar xzf helm-v2.6.1-darwin-amd64.tar.gz $ tar xzf helm-v2.7.0-darwin-amd64.tar.gz
$ mv darwin-amd64/helm /usr/local/bin $ mv darwin-amd64/helm /usr/local/bin
``` ```
On __Linux__: On __Linux__:
``` ```
$ curl -LO https://storage.googleapis.com/kubernetes-helm/helm-v2.6.1-linux-amd64.tar.gz $ curl -LO https://storage.googleapis.com/kubernetes-helm/helm-v2.7.0-linux-amd64.tar.gz
$ tar xzf helm-v2.6.1-linux-amd64.tar.gz $ tar xzf helm-v2.7.0-linux-amd64.tar.gz
$ mv linux-amd64/helm /usr/local/bin $ mv linux-amd64/helm /usr/local/bin
``` ```
@@ -67,24 +67,15 @@ $ 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:
``` ```
$ kubectl -n kube-system create sa tiller $ helm init
$ kubectl create clusterrolebinding tiller --clusterrole cluster-admin --serviceaccount=kube-system:tiller
$ helm init --service-account tiller
``` ```
(The first two commands are there to make sure that helm is allowed to
install stuff on Kubernetes, in the common case that your cluster has
role-based access control.)
### Install Fission ### Install Fission
#### Minikube #### Minikube
``` ```
$ helm install --namespace fission --set serviceType=NodePort https://github.com/fission/fission/releases/download/0.3.0/fission-all-0.3.0.tgz $ helm install --namespace fission --set serviceType=NodePort https://github.com/fission/fission/releases/download/0.4.0/fission-all-0.4.0.tgz
``` ```
The serviceType variable allows configuring the type of Kubernetes The serviceType variable allows configuring the type of Kubernetes
@@ -94,7 +85,7 @@ want to expose anything outside the cluster.
#### Cloud hosted clusters (GKE, AWS, Azure etc.) #### Cloud hosted clusters (GKE, AWS, Azure etc.)
``` ```
$ helm install --namespace fission https://github.com/fission/fission/releases/download/0.3.0/fission-all-0.3.0.tgz $ helm install --namespace fission https://github.com/fission/fission/releases/download/0.4.0/fission-all-0.4.0.tgz
``` ```
#### Minimal version #### Minimal version
@@ -104,7 +95,7 @@ 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:
``` ```
$ helm install --namespace fission https://github.com/fission/fission/releases/download/0.3.0/fission-core-0.3.0.tgz $ helm install --namespace fission https://github.com/fission/fission/releases/download/0.4.0/fission-core-0.4.0.tgz
``` ```
### Install the Fission CLI ### Install the Fission CLI
@@ -114,19 +105,19 @@ $ helm install --namespace fission https://github.com/fission/fission/releases/d
Get the CLI binary for Mac: Get the CLI binary for Mac:
``` ```
$ curl -Lo fission https://github.com/fission/fission/releases/download/0.3.0/fission-cli-osx && chmod +x fission && sudo mv fission /usr/local/bin/ $ curl -Lo fission https://github.com/fission/fission/releases/download/0.4.0/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.3.0/fission-cli-linux && chmod +x fission && sudo mv fission /usr/local/bin/ $ curl -Lo fission https://github.com/fission/fission/releases/download/0.4.0/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 For Windows, you can use the linux binary on WSL. Or you can download
this windows executable: [fission.exe](https://github.com/fission/fission/releases/download/0.3.0/fission-cli-windows.exe) this windows executable: [fission.exe](https://github.com/fission/fission/releases/download/0.4.0/fission-cli-windows.exe)
### Set environment vars ### Set environment vars
@@ -149,6 +140,13 @@ FISSION_URL and FISSION_ROUTER, respectively. Wait for services to
get IP addresses (check this with ```kubectl --namespace fission get get IP addresses (check this with ```kubectl --namespace fission get
svc```). Then: svc```). Then:
##### AWS
```
$ export FISSION_URL=http://$(kubectl --namespace fission get svc controller -o=jsonpath='{..hostname}')
$ export FISSION_ROUTER=$(kubectl --namespace fission get svc router -o=jsonpath='{..hostname}')
```
##### GCP
``` ```
$ export FISSION_URL=http://$(kubectl --namespace fission get svc controller -o=jsonpath='{..ip}') $ export FISSION_URL=http://$(kubectl --namespace fission get svc controller -o=jsonpath='{..ip}')
$ export FISSION_ROUTER=$(kubectl --namespace fission get svc router -o=jsonpath='{..ip}') $ export FISSION_ROUTER=$(kubectl --namespace fission get svc router -o=jsonpath='{..ip}')
@@ -159,7 +157,7 @@ svc```). Then:
Finally, you're ready to use Fission! Finally, you're ready to use Fission!
``` ```
$ fission env create --name nodejs --image fission/node-env:0.3.0 $ fission env create --name nodejs --image fission/node-env:0.4.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
@@ -19,9 +19,9 @@ the [upgrade guide from 0.1 to 0.2]() and then upgrade to 0.4.0.
## How to Upgrade ## How to Upgrade
1. Get the 0.4.0-rc CLI 1. Get the 0.4.0 CLI
2. Get the Fission state from v0.3 install 2. Get the Fission state from v0.3 install
3. Upgrade to Fission 0.4.0-rc 3. Upgrade to Fission 0.4.0
4. Upgrade Kubernetes cluster version to 1.7.x or higher 4. Upgrade Kubernetes cluster version to 1.7.x or higher
5. Remove all TPR definition (for Kubernetes 1.7.x) 5. Remove all TPR definition (for Kubernetes 1.7.x)
6. Restore Fission state into CRDs 6. Restore Fission state into CRDs
@@ -31,19 +31,19 @@ the [upgrade guide from 0.1 to 0.2]() and then upgrade to 0.4.0.
#### OS X #### OS X
``` ```
$ curl -Lo fission https://github.com/fission/fission/releases/download/0.4.0-rc/fission-cli-osx && chmod +x fission && sudo mv fission /usr/local/bin/ $ curl -Lo fission https://github.com/fission/fission/releases/download/0.4.0/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.4.0-rc/fission-cli-linux && chmod +x fission && sudo mv fission /usr/local/bin/ $ curl -Lo fission https://github.com/fission/fission/releases/download/0.4.0/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 For Windows, you can use the linux binary on WSL. Or you can download
this windows executable: [fission.exe](https://github.com/fission/fission/releases/download/0.4.0-rc/fission-cli-windows.exe) this windows executable: [fission.exe](https://github.com/fission/fission/releases/download/0.4.0/fission-cli-windows.exe)
### Get Fission state from v0.3 install ### Get Fission state from v0.3 install
@@ -57,7 +57,7 @@ variable `$FISSION_URL` set to point at a v0.3 Fission server.
This will create a JSON file with all your fission state in the This will create a JSON file with all your fission state in the
current directory. current directory.
### Upgrade to Fission 0.4.0-rc ### Upgrade to Fission 0.4.0
Upgrade fission with a command similar to this: Upgrade fission with a command similar to this:
@@ -80,7 +80,7 @@ Though Kubernetes will migrate TPRs to CRDs automatically when TPR definition is
fission tpr2crd delete fission tpr2crd delete
``` ```
### Restore your Fission state into Fission 0.4.0-rc ### Restore your Fission state into Fission 0.4.0
``` ```
fission tpr2crd restore --file state.json fission tpr2crd restore --file state.json
+2 -2
View File
@@ -1,6 +1,6 @@
apiVersion: v1 apiVersion: v1
name: fission-all name: fission-all
version: 0.4.0rc version: 0.4.0
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.4.0rc appVersion: 0.4.0
+3 -3
View File
@@ -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.4.0rc/fission-cli-osx && chmod +x fission && sudo mv fission /usr/local/bin/ $ curl -Lo fission https://github.com/fission/fission/releases/download/0.4.0/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.4.0rc/fission-cli-linux && chmod +x fission && sudo mv fission /usr/local/bin/ $ curl -Lo fission https://github.com/fission/fission/releases/download/0.4.0/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.4.0rc/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.4.0/fission-cli-windows.exe
2. Set the FISSION_URL and FISSION_ROUTER environment variables. 2. Set the FISSION_URL and FISSION_ROUTER environment variables.
+5 -22
View File
@@ -348,7 +348,7 @@ metadata:
svc: influxdb svc: influxdb
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
spec: spec:
type: ClusterIP type: ClusterIP
ports: ports:
- port: 8086 - port: 8086
targetPort: 8086 targetPort: 8086
@@ -400,25 +400,6 @@ spec:
svc: logger svc: logger
spec: spec:
containers: containers:
- name: logger
image: "{{ .Values.image }}:{{ .Values.imageTag }}"
imagePullPolicy: {{ .Values.pullPolicy }}
command: ["/fission-bundle"]
args: ["--logger"]
volumeMounts:
- name: container-log
mountPath: /var/log/containers
readOnly: true
- name: docker-log
mountPath: /var/lib/docker/containers
readOnly: true
- name: fission-log
mountPath: /var/log/fission
readOnly: false
ports:
- containerPort: 1234
hostPort: 1234
protocol: TCP
- name: fluentd - name: fluentd
image: {{ .Values.logger.fluentdImage }} image: {{ .Values.logger.fluentdImage }}
imagePullPolicy: {{ .Values.pullPolicy }} imagePullPolicy: {{ .Values.pullPolicy }}
@@ -439,9 +420,11 @@ spec:
secretKeyRef: secretKeyRef:
name: influxdb name: influxdb
key: password key: password
- name: FLUENTD_PATH
value: /var/log/containers/*{{.Values.functionNamespace}}*.log
volumeMounts: volumeMounts:
- name: container-log - name: container-log
mountPath: /var/log/containers mountPath: /var/log/
readOnly: true readOnly: true
- name: docker-log - name: docker-log
mountPath: /var/lib/docker/containers mountPath: /var/lib/docker/containers
@@ -453,7 +436,7 @@ spec:
volumes: volumes:
- name: container-log - name: container-log
hostPath: hostPath:
path: /var/log/containers path: /var/log/
- name: docker-log - name: docker-log
hostPath: hostPath:
path: /var/lib/docker/containers path: /var/lib/docker/containers
+6
View File
@@ -10,7 +10,9 @@ spec:
ports: ports:
- port: 80 - port: 80
targetPort: 8888 targetPort: 8888
{{ if eq .Values.serviceType "NodePort" }}
nodePort: {{ .Values.routerPort }} nodePort: {{ .Values.routerPort }}
{{ end }}
selector: selector:
svc: router svc: router
@@ -27,7 +29,9 @@ spec:
ports: ports:
- port: 80 - port: 80
targetPort: 8888 targetPort: 8888
{{ if eq .Values.serviceType "NodePort" }}
nodePort: {{ .Values.controllerPort }} nodePort: {{ .Values.controllerPort }}
{{ end }}
selector: selector:
svc: controller svc: controller
@@ -44,7 +48,9 @@ spec:
ports: ports:
- port: 4222 - port: 4222
targetPort: 4222 targetPort: 4222
{{ if eq .Values.serviceType "NodePort" }}
nodePort: {{ .Values.natsStreamingPort }} nodePort: {{ .Values.natsStreamingPort }}
{{ end }}
selector: selector:
svc: nats-streaming svc: nats-streaming
+3 -3
View File
@@ -10,16 +10,16 @@ serviceType: LoadBalancer
image: fission/fission-bundle image: fission/fission-bundle
## Image pull policy ## Image pull policy
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
## Fission image version ## Fission image version
imageTag: 0.3.0 imageTag: 0.4.0
## Fission fetcher repository ## Fission fetcher repository
fetcherImage: fission/fetcher fetcherImage: fission/fetcher
## Fission fetcher image version ## Fission fetcher image version
fetcherImageTag: 0.3.0 fetcherImageTag: 0.4.0
## Port at which Fission controller service should be exposed ## Port at which Fission controller service should be exposed
controllerPort: 31313 controllerPort: 31313
+2 -2
View File
@@ -1,6 +1,6 @@
apiVersion: v1 apiVersion: v1
name: fission-core name: fission-core
version: 0.4.0rc version: 0.4.0
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.4.0rc appVersion: 0.4.0
+3 -3
View File
@@ -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.4.0rc/fission-cli-osx && chmod +x fission && sudo mv fission /usr/local/bin/ $ curl -Lo fission https://github.com/fission/fission/releases/download/0.4.0/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.4.0rc/fission-cli-linux && chmod +x fission && sudo mv fission /usr/local/bin/ $ curl -Lo fission https://github.com/fission/fission/releases/download/0.4.0/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.4.0rc/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.4.0/fission-cli-windows.exe
2. Set the FISSION_URL and FISSION_ROUTER environment variables. 2. Set the FISSION_URL and FISSION_ROUTER environment variables.
+4
View File
@@ -10,7 +10,9 @@ spec:
ports: ports:
- port: 80 - port: 80
targetPort: 8888 targetPort: 8888
{{ if eq .Values.serviceType "NodePort" }}
nodePort: {{ .Values.routerPort }} nodePort: {{ .Values.routerPort }}
{{ end }}
selector: selector:
svc: router svc: router
@@ -27,7 +29,9 @@ spec:
ports: ports:
- port: 80 - port: 80
targetPort: 8888 targetPort: 8888
{{ if eq .Values.serviceType "NodePort" }}
nodePort: {{ .Values.controllerPort }} nodePort: {{ .Values.controllerPort }}
{{ end }}
selector: selector:
svc: controller svc: controller
+2 -2
View File
@@ -10,7 +10,7 @@ serviceType: LoadBalancer
image: fission/fission-bundle image: fission/fission-bundle
## Fission image version ## Fission image version
imageTag: 0.3.0 imageTag: 0.4.0
## Image pull policy ## Image pull policy
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
@@ -19,7 +19,7 @@ pullPolicy: IfNotPresent
fetcherImage: fission/fetcher fetcherImage: fission/fetcher
## Fission fetcher image version ## Fission fetcher image version
fetcherImageTag: 0.3.0 fetcherImageTag: 0.4.0
## Port at which Fission controller service should be exposed ## Port at which Fission controller service should be exposed
controllerPort: 31313 controllerPort: 31313
+1 -1
View File
@@ -120,7 +120,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.4.0rc\"}\n") fmt.Fprintf(w, "{\"message\": \"Fission API\", \"version\": \"0.4.0\"}\n")
} }
func (api *API) ApiVersionMismatchHandler(w http.ResponseWriter, r *http.Request) { func (api *API) ApiVersionMismatchHandler(w http.ResponseWriter, r *http.Request) {
+14
View File
@@ -0,0 +1,14 @@
FROM alpine:3.5
RUN apk update
RUN apk add --no-cache python python-dev build-base py-pip
RUN pip install --upgrade pip
RUN rm -r /root/.cache
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
ENTRYPOINT ["python"]
CMD ["server.py"]
+20 -1
View File
@@ -82,7 +82,7 @@ This is a basic example of how you can easily use asynchronous requests in your
$ fission function create --name stock --env nodejs --code stock.js $ fission function create --name stock --env nodejs --code stock.js
# Map GET /stock to your new function # Map GET /stock to your new function
$ fission route create --method GET --url /stock --function stock $ fission route create --method POST --url /stock --function stock
# Run the function. # Run the function.
$ curl -H "Content-Type: application/json" -X POST -d '{"symbol":"AAPL"}' http://$FISSION_ROUTER/stock $ curl -H "Content-Type: application/json" -X POST -d '{"symbol":"AAPL"}' http://$FISSION_ROUTER/stock
@@ -103,3 +103,22 @@ $ fission fn create --name kubeEventsSlack --env nodejs --code kubeEventsSlack.j
# Watch all services in the default namespace: # Watch all services in the default namespace:
$ fission watch create --function kubeEventsSlack --type service --ns default $ fission watch create --function kubeEventsSlack --type service --ns default
``` ```
## weather.js
In this example, the Yahoo Weather API is used to current weather at a given location.
### Usage
```bash
# Upload your function code to fission
$ fission function create --name weather --env nodejs --code weather.js
# Map GET /stock to your new function
$ fission route create --method POST --url /weather --function weather
# Run the function.
$ curl -H "Content-Type: application/json" -X POST -d '{"location":"Sieteiglesias, Spain"}' http://$FISSION_ROUTER/weather
{"text":"It is 2 celsius degrees in Sieteiglesias, Spain and Mostly Clear"}
```
+40
View File
@@ -0,0 +1,40 @@
'use strict';
const rp = require('request-promise-native');
module.exports = async function (context) {
const stringBody = JSON.stringify(context.request.body);
const body = JSON.parse(stringBody);
const location = body.location;
if (!location) {
return {
status: 400,
body: {
text: 'You must provide a location.'
}
};
}
try {
const response = await rp(`https://query.yahooapis.com/v1/public/yql?q=select item.condition from weather.forecast where woeid in (select woeid from geo.places(1) where text="${location}") and u="c"&format=json`);
const condition = JSON.parse(response).query.results.channel.item.condition;
const text = condition.text;
const temperature = condition.temp;
return {
status: 200,
body: {
text: `It is ${temperature} celsius degrees in ${location} and ${text}`
},
headers: {
'Content-Type': 'application/json'
}
};
} catch (e) {
console.error(e);
return {
status: 500,
body: e
};
}
}
+62
View File
@@ -0,0 +1,62 @@
This is an example of creating a deployment package with multiple
files including some static data in text file.
### Create an environment
```
fission env create --name python --image fission/python-env:0.4.0rc --version 2
```
### Create a zip file with all your files
```
zip -jr multifile.zip *.py *.txt
```
### Create a function
Since there are multiple files, you have to specify an _entrypoint_ to
for the function. Its format is `<file name>.<function name>`. In our
example, that's `main.main`, to run function `main` in `main.py`.
```
fission function create --name multifile --env python --code multifile.zip --entrypoint main.main
```
### Test it
```
fission function test --name multifile
```
You should see the "Hello, world" message.
## Updating the function
### Edit a file
```
echo "I said hellooooo!" > message.txt
```
### Update the deployment package
```
zip -jr multifile.zip *.py *.txt
```
### Update the function
```
fission function update --name multifile --code multifile.zip
```
### Test it
```
fission function test --name multifile
```
You should now see your new, edited message.
+11
View File
@@ -0,0 +1,11 @@
from flask import current_app
import sys
import readfile
import os
def main():
current_app.logger.info("Hi")
current_dir = os.path.dirname(__file__)
return readfile.readFile(os.path.join(current_dir, "message.txt"))
+1
View File
@@ -0,0 +1 @@
Hello, world!
+3
View File
@@ -0,0 +1,3 @@
def readFile(name):
with open(name) as f:
return f.read()
+4
View File
@@ -0,0 +1,4 @@
def main():
# You can return any http status code you like, simply place a comma after
# your return statement, and typing in the status code.
return "Not Found\n", 404
-12
View File
@@ -9,7 +9,6 @@ import (
"github.com/fission/fission/buildermgr" "github.com/fission/fission/buildermgr"
"github.com/fission/fission/controller" "github.com/fission/fission/controller"
"github.com/fission/fission/kubewatcher" "github.com/fission/fission/kubewatcher"
"github.com/fission/fission/logger"
"github.com/fission/fission/mqtrigger" "github.com/fission/fission/mqtrigger"
"github.com/fission/fission/poolmgr" "github.com/fission/fission/poolmgr"
"github.com/fission/fission/router" "github.com/fission/fission/router"
@@ -41,11 +40,6 @@ func runKubeWatcher(routerUrl string) {
} }
} }
func runLogger() {
logger.Start()
log.Fatalf("Error: Logger exited.")
}
func runTimer(routerUrl string) { func runTimer(routerUrl string) {
err := timer.Start(routerUrl) err := timer.Start(routerUrl)
if err != nil { if err != nil {
@@ -122,7 +116,6 @@ Usage:
fission-bundle --kubewatcher [--routerUrl=<url>] fission-bundle --kubewatcher [--routerUrl=<url>]
fission-bundle --storageServicePort=<port> --filePath=<filePath> fission-bundle --storageServicePort=<port> --filePath=<filePath>
fission-bundle --builderMgrPort=<port> [--storageSvcUrl=<url>] [--envbuilder-namespace=<namespace>] fission-bundle --builderMgrPort=<port> [--storageSvcUrl=<url>] [--envbuilder-namespace=<namespace>]
fission-bundle --logger
fission-bundle --timer [--routerUrl=<url>] fission-bundle --timer [--routerUrl=<url>]
fission-bundle --mqt [--routerUrl=<url>] fission-bundle --mqt [--routerUrl=<url>]
Options: Options:
@@ -138,7 +131,6 @@ Options:
--filePath=<filePath> Directory to store functions in. --filePath=<filePath> Directory to store functions in.
--namespace=<namespace> Kubernetes namespace in which to run function containers. Defaults to 'fission-function'. --namespace=<namespace> Kubernetes namespace in which to run function containers. Defaults to 'fission-function'.
--kubewatcher Start Kubernetes events watcher. --kubewatcher Start Kubernetes events watcher.
--logger Start logger.
--timer Start Timer. --timer Start Timer.
--mqt Start message queue trigger. --mqt Start message queue trigger.
` `
@@ -174,10 +166,6 @@ Options:
runKubeWatcher(routerUrl) runKubeWatcher(routerUrl)
} }
if arguments["--logger"] == true {
runLogger()
}
if arguments["--timer"] == true { if arguments["--timer"] == true {
runTimer(routerUrl) runTimer(routerUrl)
} }
+8 -7
View File
@@ -96,14 +96,15 @@ func (influx InfluxDB) GetLogs(filter LogFilter) ([]LogEntry, error) {
log.Fatal(err) log.Fatal(err)
} }
logEntries = append(logEntries, LogEntry{ logEntries = append(logEntries, LogEntry{
//The attributes of the LogEntry are selected as relative to their position in InfluxDB's line protocol response
Timestamp: t, Timestamp: t,
Container: row[2].(string), Container: row[2].(string), //docker_container_id
FuncName: row[3].(string), FuncName: row[8].(string), //kubernetes_labels_functionName
FuncUid: row[4].(string), FuncUid: row[3].(string), //funcuid
Message: strings.TrimSuffix(row[5].(string), "\n"), Message: strings.TrimSuffix(row[17].(string), "\n"), //log field
Namespace: row[6].(string), Namespace: row[14].(string), //kubernetes_namespace_name
Pod: row[7].(string), Pod: row[15].(string), //kubernetes_pod_name
Stream: row[8].(string), Stream: row[18].(string), //stream
}) })
} }
} }
+1 -1
View File
@@ -26,7 +26,7 @@ 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.4.0rc" app.Version = "0.4.0"
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
cli.StringFlag{Name: "server", Usage: "Fission server URL", EnvVar: "FISSION_URL"}, cli.StringFlag{Name: "server", Usage: "Fission server URL", EnvVar: "FISSION_URL"},
+14 -13
View File
@@ -128,27 +128,28 @@ build_and_push_all_envs() {
version=$1 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" ""
build_and_push_env_image "$version" "nodejs" "node-env" "debian" build_and_push_env_image "$version" "nodejs" "node-env" "debian"
build_and_push_env_image "$version" "binary" "binary-env" "" build_and_push_env_image "$version" "binary" "binary-env" ""
build_and_push_env_image "$version" "dotnet" "dotnet-env" "" build_and_push_env_image "$version" "dotnet" "dotnet-env" ""
build_and_push_env_image "$version" "dotnet20" "dotnet20-env" "" build_and_push_env_image "$version" "dotnet20" "dotnet20-env" ""
build_and_push_env_image "$version" "go" "go-env" "" build_and_push_env_image "$version" "go" "go-env" ""
build_and_push_env_image "$version" "perl" "perl-env" "" build_and_push_env_image "$version" "perl" "perl-env" ""
build_and_push_env_image "$version" "php7" "php-env" "" build_and_push_env_image "$version" "php7" "php-env" ""
build_and_push_env_image "$version" "python3" "python-env" "" build_and_push_env_image "$version" "python" "python-env" ""
build_and_push_env_image "$version" "ruby" "ruby-env" "" build_and_push_env_image "$version" "python" "python-env" "2.7"
build_and_push_env_image "$version" "ruby" "ruby-env" ""
} }
build_charts() { build_charts() {
version=$1 version=$1
mkdir -p $BUILDDIR/charts mkdir -p $BUILDDIR/charts
pushd $DIR/charts pushd $DIR/charts
for c in all core find . -iname *.~?~ | xargs rm
for c in fission-all fission-core
do do
tgz=fission-$c-$version.tgz helm package $c/
tar czvf $tgz fission-$c/ mv *.tgz $BUILDDIR/charts/
mv $tgz $BUILDDIR/charts/
done done
popd popd
} }
+3 -1
View File
@@ -35,7 +35,7 @@ ENV DEBIAN_FRONTEND noninteractive
# Install build tools # Install build tools
RUN apt-get -qq update && \ RUN apt-get -qq update && \
apt-get install -y -qq curl ca-certificates gcc make bash sudo && \ apt-get install -y -qq curl ca-certificates gcc g++ make bash sudo && \
apt-get install -y -qq --reinstall lsb-base lsb-release && \ apt-get install -y -qq --reinstall lsb-base lsb-release && \
# Install logging agent and required gems # Install logging agent and required gems
/usr/bin/curl -sSL https://toolbelt.treasuredata.com/sh/install-ubuntu-xenial-td-agent2.sh | sh && \ /usr/bin/curl -sSL https://toolbelt.treasuredata.com/sh/install-ubuntu-xenial-td-agent2.sh | sh && \
@@ -45,6 +45,8 @@ RUN apt-get -qq update && \
td-agent-gem install --no-document fluent-plugin-google-cloud -v 0.5.2 && \ td-agent-gem install --no-document fluent-plugin-google-cloud -v 0.5.2 && \
td-agent-gem install --no-document fluent-plugin-detect-exceptions -v 0.0.4 && \ td-agent-gem install --no-document fluent-plugin-detect-exceptions -v 0.0.4 && \
td-agent-gem install --no-document fluent-plugin-influxdb && \ td-agent-gem install --no-document fluent-plugin-influxdb && \
td-agent-gem install --no-document fluent-plugin-kubernetes_metadata_filter && \
td-agent-gem install --no-document fluent-plugin-flatten-hash && \
# Remove build tools # Remove build tools
apt-get remove -y -qq gcc make && \ apt-get remove -y -qq gcc make && \
apt-get autoremove -y -qq && \ apt-get autoremove -y -qq && \
+1 -1
View File
@@ -1,2 +1,2 @@
#!/bin/sh #!/bin/sh
docker build -t fission-daemonset-fluentd:latest . docker build -t fission-daemonset-fluentd:latest .
+20 -14
View File
@@ -4,26 +4,32 @@
<source> <source>
type tail type tail
format json format json
time_key time time_key time
path /var/log/fission/*.log path "#{ENV['FLUENTD_PATH']}"
time_format %Y-%m-%dT%H:%M:%S.%NZ time_format %Y-%m-%dT%H:%M:%S.%NZ
tag fission.* tag fission.*
read_from_head true read_from_head true
refresh_interval 5 refresh_interval 5
</source> </source>
<filter fission.**>
type kubernetes_metadata
</filter>
<filter fission.**>
type flatten_hash
separator _
</filter>
<match fission.**> <match fission.**>
type record_reformer type record_reformer
enable_ruby false enable_ruby false
tag log tag log
<record> <record>
namespace ${tag_parts[4]} funcuid ${kubernetes_labels_functionUid}
pod ${tag_parts[5]} </record>
container ${tag_parts[6]}
funcname ${tag_parts[7]}
funcuid ${tag_parts[8]}
</record>
</match> </match>
<match **> <match **>
@@ -35,7 +41,7 @@
password "#{ENV['INFLUXDB_PASSWD']}" password "#{ENV['INFLUXDB_PASSWD']}"
use_ssl false use_ssl false
time_precision s time_precision s
tag_keys ["funcuid", "pod"] tag_keys ["funcuid"]
sequence_tag _seq sequence_tag _seq
buffer_type file buffer_type file
buffer_path /var/log/fission/fluentd.buffer buffer_path /var/log/fission/fluentd.buffer
@@ -45,4 +51,4 @@
retry_limit 10 retry_limit 10
retry_wait 1.0 retry_wait 1.0
num_threads 2 num_threads 2
</match> </match>
-216
View File
@@ -1,216 +0,0 @@
/*
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 logger
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strings"
"github.com/fission/fission"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
log "github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
func makelogRequestTracker() logRequestTracker {
return logRequestTracker{
logMap: make(map[string]LogRequest),
}
}
func (l logRequestTracker) Add(logReq LogRequest) {
l.Lock()
l.logMap[logReq.Pod] = logReq
l.Unlock()
}
func (l logRequestTracker) Get(pod string) LogRequest {
l.RLock()
logReq, ok := l.logMap[pod]
l.RUnlock()
if ok {
return logReq
}
return LogRequest{}
}
func (l logRequestTracker) Remove(logReq LogRequest) {
l.Lock()
delete(l.logMap, logReq.Pod)
l.Unlock()
}
// Get a kubernetes client using the pod's service account. This only
// works when we're running inside a kubernetes cluster.
func getKubernetesClient() (*kubernetes.Clientset, error) {
// creates the in-cluster config
config, err := rest.InClusterConfig()
if err != nil {
log.Printf("Error getting kubernetes client config: %v", err)
return nil, err
}
// creates the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
log.Printf("Error getting kubernetes client: %v", err)
return nil, err
}
return clientset, nil
}
// make sure that the targetPath is a legitimate path for security purpose
func validateFilePath(targetPath string, expectedPathPrefix string) bool {
targetPath = filepath.Clean(targetPath)
return strings.HasPrefix(targetPath, expectedPathPrefix)
}
// The ContainerID is consist of container engine type (docker://) and uuid of container.
// (e.g., docker://f4ca66baaa715030e20273aaf5232635a144165f1cd8e34ca5175064c245b679)
// This function tries to extract container uuid from ContainerID.
func parseContainerString(containerID string) (string, error) {
// Trim the quotes and split the type and ID.
parts := strings.Split(strings.Trim(containerID, "\""), "://")
if len(parts) != 2 {
return "", fmt.Errorf("invalid container ID: %q", containerID)
}
_, ID := parts[0], parts[1]
return ID, nil
}
func getcontainerID(kubeClient *kubernetes.Clientset, namespace, pod, container string) (string, error) {
podInfo, err := kubeClient.CoreV1().Pods(namespace).Get(pod, v1.GetOptions{})
if err != nil {
log.Printf("Failed to get pod info: %v", err)
return "", err
}
var containerID string
for _, c := range podInfo.Status.ContainerStatuses {
if c.Name == container {
containerID, err = parseContainerString(c.ContainerID)
if err != nil {
log.Printf("Failed to get container id: %v", err)
return "", err
}
return containerID, nil
}
}
return "", fission.MakeError(404, "no matching container is found")
}
func getContainerLogPath(logReq LogRequest) (string, bool) {
logPath := fmt.Sprintf("/var/lib/docker/containers/%s/%s-json.log", logReq.ContainerID, logReq.ContainerID)
if !validateFilePath(logPath, "/var/lib/docker/containers") {
return "", false
}
return logPath, true
}
func getFissionLogSymlinkPath(logReq LogRequest) (string, bool) {
// pass function related information through a symlink name
logSymLink := fmt.Sprintf("/var/log/fission/%s.%s.%s.%s.%s.log", logReq.Namespace, logReq.Pod, logReq.ContainerID, logReq.FuncName, logReq.FuncUid)
if !validateFilePath(logSymLink, "/var/log/fission") {
return "", false
}
return logSymLink, true
}
func createLogSymlink(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, "Failed to read request", 500)
return
}
logReq := LogRequest{}
if err = json.Unmarshal(body, &logReq); err != nil {
w.Write([]byte(fmt.Sprintf("%v", err)))
return
}
kubernetesClient, err := getKubernetesClient()
if err != nil {
log.Warningf("Failed to get kubernetes client: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
containerID, err := getcontainerID(kubernetesClient, logReq.Namespace, logReq.Pod, logReq.Container)
if err != nil || containerID == "" {
log.Warningf("Failed to get container id: %v", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
logReq.ContainerID = containerID
containerLogFilePath, isValidLogPath := getContainerLogPath(logReq)
fissionLogSymlinkPath, isValidSymlinkPath := getFissionLogSymlinkPath(logReq)
if !isValidLogPath || !isValidSymlinkPath {
w.WriteHeader(http.StatusBadRequest)
return
}
err = os.Symlink(containerLogFilePath, fissionLogSymlinkPath)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
logInfo.Add(logReq)
w.WriteHeader(http.StatusOK)
}
func removeLogSymlink(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
pod := vars["pod"]
logReq := logInfo.Get(pod)
if logReq.Pod == "" {
w.WriteHeader(http.StatusInternalServerError)
return
}
fissionLogSymlinkPath, isValidSymlinkPath := getFissionLogSymlinkPath(logReq)
if !isValidSymlinkPath {
w.WriteHeader(http.StatusBadRequest)
return
}
err := os.Remove(fissionLogSymlinkPath)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
var logInfo logRequestTracker
func Start() {
logInfo = makelogRequestTracker()
r := mux.NewRouter()
r.HandleFunc("/v1/log", createLogSymlink).Methods("POST")
r.HandleFunc("/v1/log/{pod}", removeLogSymlink).Methods("DELETE")
address := fmt.Sprintf(":%v", 1234)
log.Printf("starting logger at port %s", address)
log.Fatal(http.ListenAndServe(address, handlers.LoggingHandler(os.Stdout, r)))
}
-33
View File
@@ -43,7 +43,6 @@ import (
"github.com/fission/fission/crd" "github.com/fission/fission/crd"
"github.com/fission/fission/environments/fetcher" "github.com/fission/fission/environments/fetcher"
fetcherClient "github.com/fission/fission/environments/fetcher/client" fetcherClient "github.com/fission/fission/environments/fetcher/client"
"github.com/fission/fission/logger"
) )
const POOLMGR_INSTANCEID_LABEL string = "poolmgrInstanceId" const POOLMGR_INSTANCEID_LABEL string = "poolmgrInstanceId"
@@ -348,9 +347,6 @@ func (gp *GenericPool) specializePod(pod *apiv1.Pod, metadata *metav1.ObjectMeta
return err return err
} }
// Tell logging helper about this function invocation
gp.setupLogging(pod, metadata)
// get function run container to specialize // get function run container to specialize
log.Printf("[%v] specializing pod", metadata.Name) log.Printf("[%v] specializing pod", metadata.Name)
@@ -682,32 +678,3 @@ func (gp *GenericPool) destroy() error {
return nil return nil
} }
// Calls the logging daemonset pod on the node where the given pod is
// running.
func (gp *GenericPool) setupLogging(pod *apiv1.Pod, metadata *metav1.ObjectMeta) {
logReq := logger.LogRequest{
Namespace: pod.Namespace,
Pod: pod.Name,
Container: gp.env.Metadata.Name,
FuncName: metadata.Name,
FuncUid: string(metadata.UID),
}
reqbody, err := json.Marshal(logReq)
if err != nil {
log.Printf("Error creating log request")
return
}
go func() {
loggerUrl := fmt.Sprintf("http://%s:1234/v1/log", pod.Status.HostIP)
resp, err := http.Post(loggerUrl, "application/json", bytes.NewReader(reqbody))
if err != nil {
log.Printf("Error connecting to %s log daemonset pod: %v", pod.Spec.NodeName, err)
} else {
if resp.StatusCode != 200 {
log.Printf("Error from %s log daemonset pod: %s", pod.Spec.NodeName, resp.Status)
}
resp.Body.Close()
}
}()
}
+3 -19
View File
@@ -36,8 +36,6 @@ type (
// functionReferenceResolver provides a resolver to turn a function // functionReferenceResolver provides a resolver to turn a function
// reference into a resolveResult // reference into a resolveResult
functionReferenceResolver struct { functionReferenceResolver struct {
fissionClient *crd.FissionClient
// FunctionReference -> function metadata // FunctionReference -> function metadata
refCache *cache.Cache refCache *cache.Cache
@@ -68,28 +66,14 @@ const (
resolveResultSingleFunction = iota resolveResultSingleFunction = iota
) )
func makeFunctionReferenceResolver(fissionClient *crd.FissionClient) *functionReferenceResolver { func makeFunctionReferenceResolver(store k8sCache.Store) *functionReferenceResolver {
frr := &functionReferenceResolver{ frr := &functionReferenceResolver{
fissionClient: fissionClient, refCache: cache.MakeCache(time.Minute, 0),
refCache: cache.MakeCache(time.Minute, 0), store: store,
} }
return frr return frr
} }
// Sync starts syncing crd function resources from k8s api server
func (frr *functionReferenceResolver) Sync(crdClient *rest.RESTClient) {
stopCh := make(chan struct{})
store, controller := makeK8SCache(crdClient)
frr.stopCh = stopCh
frr.store = store
go controller.Run(stopCh)
}
// Stop stops crd resources syncing
func (frr *functionReferenceResolver) Stop() {
frr.stopCh <- struct{}{}
}
func makeK8SCache(crdClient *rest.RESTClient) (k8sCache.Store, k8sCache.Controller) { func makeK8SCache(crdClient *rest.RESTClient) (k8sCache.Store, k8sCache.Controller) {
watchlist := k8sCache.NewListWatchFromClient(crdClient, "functions", metav1.NamespaceDefault, fields.Everything()) watchlist := k8sCache.NewListWatchFromClient(crdClient, "functions", metav1.NamespaceDefault, fields.Everything())
listWatch := &k8sCache.ListWatch{ listWatch := &k8sCache.ListWatch{
+40 -49
View File
@@ -17,6 +17,7 @@ limitations under the License.
package router package router
import ( import (
"context"
"log" "log"
"net/http" "net/http"
"time" "time"
@@ -24,8 +25,6 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
k8sCache "k8s.io/client-go/tools/cache" k8sCache "k8s.io/client-go/tools/cache"
@@ -37,30 +36,42 @@ import (
type HTTPTriggerSet struct { type HTTPTriggerSet struct {
*functionServiceMap *functionServiceMap
*mutableRouter *mutableRouter
fissionClient *crd.FissionClient fissionClient *crd.FissionClient
poolmgr *poolmgrClient.Client poolmgr *poolmgrClient.Client
resolver *functionReferenceResolver resolver *functionReferenceResolver
triggers []crd.HTTPTrigger crdClient *rest.RESTClient
triggerStore k8sCache.Store triggers []crd.HTTPTrigger
functions []crd.Function triggerStore k8sCache.Store
funcStore k8sCache.Store triggerController k8sCache.Controller
crdClient *rest.RESTClient functions []crd.Function
funcStore k8sCache.Store
funcController k8sCache.Controller
} }
func makeHTTPTriggerSet(fmap *functionServiceMap, fissionClient *crd.FissionClient, func makeHTTPTriggerSet(fmap *functionServiceMap, fissionClient *crd.FissionClient,
poolmgr *poolmgrClient.Client, resolver *functionReferenceResolver, crdClient *rest.RESTClient) *HTTPTriggerSet { poolmgr *poolmgrClient.Client, crdClient *rest.RESTClient) (*HTTPTriggerSet, k8sCache.Store, k8sCache.Store) {
triggers := make([]crd.HTTPTrigger, 1) httpTriggerSet := &HTTPTriggerSet{
return &HTTPTriggerSet{
functionServiceMap: fmap, functionServiceMap: fmap,
triggers: triggers, triggers: []crd.HTTPTrigger{},
fissionClient: fissionClient, fissionClient: fissionClient,
poolmgr: poolmgr, poolmgr: poolmgr,
resolver: resolver,
crdClient: crdClient, crdClient: crdClient,
} }
var tStore, fnStore k8sCache.Store
var tController, fnController k8sCache.Controller
if httpTriggerSet.crdClient != nil {
tStore, tController = httpTriggerSet.initTriggerController()
httpTriggerSet.triggerStore = tStore
httpTriggerSet.triggerController = tController
fnStore, fnController = httpTriggerSet.initFunctionController()
httpTriggerSet.funcStore = fnStore
httpTriggerSet.funcController = fnController
}
return httpTriggerSet, tStore, fnStore
} }
func (ts *HTTPTriggerSet) subscribeRouter(mr *mutableRouter) { func (ts *HTTPTriggerSet) subscribeRouter(ctx context.Context, mr *mutableRouter, resolver *functionReferenceResolver) {
ts.resolver = resolver
ts.mutableRouter = mr ts.mutableRouter = mr
mr.updateRouter(ts.getRouter()) mr.updateRouter(ts.getRouter())
@@ -69,8 +80,8 @@ func (ts *HTTPTriggerSet) subscribeRouter(mr *mutableRouter) {
log.Printf("Skipping continuous trigger updates") log.Printf("Skipping continuous trigger updates")
return return
} }
go ts.watchTriggers() go ts.runWatcher(ctx, ts.funcController)
go ts.watchFunctions() go ts.runWatcher(ctx, ts.triggerController)
} }
func defaultHomeHandler(w http.ResponseWriter, r *http.Request) { func defaultHomeHandler(w http.ResponseWriter, r *http.Request) {
@@ -140,17 +151,9 @@ func (ts *HTTPTriggerSet) updateTriggerStatusFailed(ht *crd.HTTPTrigger, err err
// TODO // TODO
} }
func (ts *HTTPTriggerSet) watchTriggers() { func (ts *HTTPTriggerSet) initTriggerController() (k8sCache.Store, k8sCache.Controller) {
watchlist := k8sCache.NewListWatchFromClient(ts.crdClient, "httptriggers", metav1.NamespaceDefault, fields.Everything())
listWatch := &k8sCache.ListWatch{
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
return watchlist.List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
return watchlist.Watch(options)
},
}
resyncPeriod := 30 * time.Second resyncPeriod := 30 * time.Second
listWatch := k8sCache.NewListWatchFromClient(ts.crdClient, "httptriggers", metav1.NamespaceDefault, fields.Everything())
store, controller := k8sCache.NewInformer(listWatch, &crd.HTTPTrigger{}, resyncPeriod, store, controller := k8sCache.NewInformer(listWatch, &crd.HTTPTrigger{}, resyncPeriod,
k8sCache.ResourceEventHandlerFuncs{ k8sCache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) { AddFunc: func(obj interface{}) {
@@ -163,25 +166,12 @@ func (ts *HTTPTriggerSet) watchTriggers() {
ts.syncTriggers() ts.syncTriggers()
}, },
}) })
ts.triggerStore = store return store, controller
stop := make(chan struct{})
defer func() {
stop <- struct{}{}
}()
controller.Run(stop)
} }
func (ts *HTTPTriggerSet) watchFunctions() { func (ts *HTTPTriggerSet) initFunctionController() (k8sCache.Store, k8sCache.Controller) {
watchlist := k8sCache.NewListWatchFromClient(ts.crdClient, "functions", metav1.NamespaceDefault, fields.Everything())
listWatch := &k8sCache.ListWatch{
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
return watchlist.List(options)
},
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
return watchlist.Watch(options)
},
}
resyncPeriod := 30 * time.Second resyncPeriod := 30 * time.Second
listWatch := k8sCache.NewListWatchFromClient(ts.crdClient, "functions", metav1.NamespaceDefault, fields.Everything())
store, controller := k8sCache.NewInformer(listWatch, &crd.Function{}, resyncPeriod, store, controller := k8sCache.NewInformer(listWatch, &crd.Function{}, resyncPeriod,
k8sCache.ResourceEventHandlerFuncs{ k8sCache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) { AddFunc: func(obj interface{}) {
@@ -206,12 +196,13 @@ func (ts *HTTPTriggerSet) watchFunctions() {
ts.syncTriggers() ts.syncTriggers()
}, },
}) })
ts.funcStore = store return store, controller
stop := make(chan struct{}) }
defer func() {
stop <- struct{}{} func (ts *HTTPTriggerSet) runWatcher(ctx context.Context, controller k8sCache.Controller) {
go func() {
controller.Run(ctx.Done())
}() }()
controller.Run(stop)
} }
func (ts *HTTPTriggerSet) syncTriggers() { func (ts *HTTPTriggerSet) syncTriggers() {
+10 -11
View File
@@ -40,6 +40,7 @@ Its job is to:
package router package router
import ( import (
"context"
"fmt" "fmt"
"log" "log"
"net/http" "net/http"
@@ -57,15 +58,15 @@ import (
// request url ---[trigger]---> Function(name, deployment) ----[deployment]----> Function(name, uid) ----[pool mgr]---> k8s service url // request url ---[trigger]---> Function(name, deployment) ----[deployment]----> Function(name, uid) ----[pool mgr]---> k8s service url
func router(httpTriggerSet *HTTPTriggerSet) *mutableRouter { func router(ctx context.Context, httpTriggerSet *HTTPTriggerSet, resolver *functionReferenceResolver) *mutableRouter {
muxRouter := mux.NewRouter() muxRouter := mux.NewRouter()
mr := NewMutableRouter(muxRouter) mr := NewMutableRouter(muxRouter)
httpTriggerSet.subscribeRouter(mr) httpTriggerSet.subscribeRouter(ctx, mr, resolver)
return mr return mr
} }
func serve(port int, httpTriggerSet *HTTPTriggerSet) { func serve(ctx context.Context, port int, httpTriggerSet *HTTPTriggerSet, resolver *functionReferenceResolver) {
mr := router(httpTriggerSet) 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, handlers.LoggingHandler(os.Stdout, mr))
} }
@@ -79,12 +80,10 @@ func Start(port int, poolmgrUrl string) {
} }
restClient := fissionClient.GetCrdClient() restClient := fissionClient.GetCrdClient()
poolmgr := poolmgrClient.MakeClient(poolmgrUrl) poolmgr := poolmgrClient.MakeClient(poolmgrUrl)
resolver := makeFunctionReferenceResolver(fissionClient) triggers, _, fnStore := makeHTTPTriggerSet(fmap, fissionClient, poolmgr, restClient)
resolver.Sync(restClient) resolver := makeFunctionReferenceResolver(fnStore)
defer func() {
resolver.Stop()
}()
triggers := makeHTTPTriggerSet(fmap, fissionClient, poolmgr, resolver, restClient)
log.Printf("Starting router at port %v\n", port) log.Printf("Starting router at port %v\n", port)
serve(port, triggers) ctx, cancel := context.WithCancel(context.Background())
defer cancel()
serve(ctx, port, triggers, resolver)
} }
+5 -2
View File
@@ -17,6 +17,7 @@ limitations under the License.
package router package router
import ( import (
"context"
"fmt" "fmt"
"testing" "testing"
"time" "time"
@@ -58,7 +59,7 @@ func TestRouter(t *testing.T) {
frr.refCache.Set(nfr, rr) frr.refCache.Set(nfr, rr)
// HTTP trigger set with a trigger for this function // HTTP trigger set with a trigger for this function
triggers := makeHTTPTriggerSet(fmap, nil, nil, frr, nil) triggers, _, _ := makeHTTPTriggerSet(fmap, nil, nil, nil)
triggerUrl := "/foo" triggerUrl := "/foo"
triggers.triggers = append(triggers.triggers, triggers.triggers = append(triggers.triggers,
crd.HTTPTrigger{ crd.HTTPTrigger{
@@ -75,7 +76,9 @@ func TestRouter(t *testing.T) {
// run the router // run the router
port := 4242 port := 4242
go serve(port, triggers) ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go serve(ctx, port, triggers, frr)
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
// hit the router // hit the router
+5 -2
View File
@@ -13,6 +13,7 @@ source $(dirname $0)/test_utils.sh
REPO=gcr.io/fission-ci REPO=gcr.io/fission-ci
IMAGE=$REPO/fission-bundle IMAGE=$REPO/fission-bundle
FETCHER_IMAGE=$REPO/fetcher FETCHER_IMAGE=$REPO/fetcher
FLUENTD_IMAGE=gcr.io/fission-ci/fluentd
TAG=test TAG=test
build_and_push_fission_bundle $IMAGE:$TAG build_and_push_fission_bundle $IMAGE:$TAG
@@ -21,12 +22,14 @@ build_and_push_fetcher $FETCHER_IMAGE:$TAG
build_builder build_builder
ENV='python3' ENV='python'
build_and_push_env_runtime $ENV $REPO/$ENV-env:$TAG build_and_push_env_runtime $ENV $REPO/$ENV-env:$TAG
build_and_push_env_builder $ENV $REPO/$ENV-env-builder:$TAG build_and_push_env_builder $ENV $REPO/$ENV-env-builder:$TAG
build_and_push_fluentd $FLUENTD_IMAGE:$TAG
build_fission_cli build_fission_cli
install_and_test $IMAGE $TAG $FETCHER_IMAGE $TAG install_and_test $IMAGE $TAG $FETCHER_IMAGE $TAG $FLUENTD_IMAGE $TAG
+23 -2
View File
@@ -56,6 +56,19 @@ build_builder() {
popd popd
} }
build_and_push_fluentd(){
image_tag=$1
pushd $ROOT/logger/fluentd
docker build -t $image_tag .
gcloud_login
gcloud docker -- push $image_tag
popd
}
build_and_push_env_runtime() { build_and_push_env_runtime() {
env=$1 env=$1
image_tag=$2 image_tag=$2
@@ -110,13 +123,17 @@ helm_install_fission() {
fetcherImageTag=$5 fetcherImageTag=$5
controllerNodeport=$6 controllerNodeport=$6
routerNodeport=$7 routerNodeport=$7
fluentdImage=$8
ns=f-$id ns=f-$id
fns=f-func-$id fns=f-func-$id
helmVars=image=$image,imageTag=$imageTag,fetcherImage=$fetcherImage,fetcherImageTag=$fetcherImageTag,functionNamespace=$fns,controllerPort=$controllerNodeport,routerPort=$routerNodeport,pullPolicy=Always,analytics=false helmVars=image=$image,imageTag=$imageTag,fetcherImage=$fetcherImage,fetcherImageTag=$fetcherImageTag,functionNamespace=$fns,controllerPort=$controllerNodeport,routerPort=$routerNodeport,pullPolicy=Always,analytics=false,logger.fluentdImage=$fluentdImage
helm_setup helm_setup
echo "Deleting failed releases"
helm list --failed -q|xargs -I@ bash -c "helm delete @"
echo "Installing fission" echo "Installing fission"
helm install \ helm install \
@@ -127,6 +144,8 @@ helm_install_fission() {
--namespace $ns \ --namespace $ns \
--debug \ --debug \
$ROOT/charts/fission-all $ROOT/charts/fission-all
helm list
} }
wait_for_service() { wait_for_service() {
@@ -275,6 +294,8 @@ install_and_test() {
imageTag=$2 imageTag=$2
fetcherImage=$3 fetcherImage=$3
fetcherImageTag=$4 fetcherImageTag=$4
fluentdImage=$5
fluentdImageTag=$6
controllerPort=31234 controllerPort=31234
routerPort=31235 routerPort=31235
@@ -283,7 +304,7 @@ install_and_test() {
id=$(generate_test_id) id=$(generate_test_id)
trap "helm_uninstall_fission $id" EXIT trap "helm_uninstall_fission $id" EXIT
if ! helm_install_fission $id $image $imageTag $fetcherImage $fetcherImageTag $controllerPort $routerPort if ! helm_install_fission $id $image $imageTag $fetcherImage $fetcherImageTag $controllerPort $routerPort $fluentdImage:$fluentdImageTag
then then
dump_logs $id dump_logs $id
exit 1 exit 1
+8
View File
@@ -0,0 +1,8 @@
module.exports = async function(context) {
console.log("log test log test log test")
return {
status: 200,
body: "Log, test!\n"
};
}
+58
View File
@@ -0,0 +1,58 @@
#!/bin/bash
set -euo pipefail
ROOT=$(dirname $0)/../..
fn=nodejs-logtest
function cleanup {
echo "Cleanup route"
var=$(fission route list | grep $fn | awk '{print $1;}')
fission route delete --name $var
fission function delete --name $fn
}
# Create a hello world function in nodejs, test it with an http trigger
echo "Pre-test cleanup"
fission env delete --name nodejs || true
echo "Creating nodejs env"
fission env create --name nodejs --image fission/node-env
trap "fission env delete --name nodejs" EXIT
echo "Creating function"
fission fn create --name $fn --env nodejs --code log.js
trap "fission fn delete --name $fn" EXIT
echo "Creating route"
fission route create --function $fn --url /logtest --method GET
echo "Waiting for router to catch up"
sleep 3
echo "Doing 4 HTTP GET on the function's route"
curl http://$FISSION_ROUTER/logtest
curl http://$FISSION_ROUTER/logtest
curl http://$FISSION_ROUTER/logtest
curl http://$FISSION_ROUTER/logtest
echo "Grabbing logs, should have 4 calls in logs"
sleep 15
echo "woke up"
logs=$(fission function logs --name $fn)
num=$(echo "$logs" | grep 'log test' | wc -l)
echo $num
if [ $num -ne 4 ]
then
echo "Test Failed"
trap cleanup EXIT
fi
cleanup
echo "All done."