Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db372c11eb | ||
|
|
6a1da19e73 | ||
|
|
816fd25a6c | ||
|
|
c03bb01bca | ||
|
|
bed189c715 | ||
|
|
80a4bcbcff | ||
|
|
f420383882 | ||
|
|
fac508c7e0 | ||
|
|
64a82747a9 | ||
|
|
5f9e54bbeb | ||
|
|
8d6b33258d | ||
|
|
be84a864fb | ||
|
|
dff34b08e9 | ||
|
|
1e6b7a4fc8 | ||
|
|
eed3018458 | ||
|
|
fa810e6f80 | ||
|
|
b1483e5e78 | ||
|
|
43fea01bd9 | ||
|
|
49169e672d | ||
|
|
140b132c8e | ||
|
|
36008f28d8 | ||
|
|
8fc1bf4bc1 | ||
|
|
2247d3118a | ||
|
|
04531850d5 | ||
|
|
13a58e715d | ||
|
|
b2678783b6 | ||
|
|
da820186f0 | ||
|
|
7bb397dfee | ||
|
|
8a097abf9b | ||
|
|
6d0ebfd881 | ||
|
|
310183a944 | ||
|
|
8fc3479428 | ||
|
|
b2883a30de | ||
|
|
8b40ad0b33 | ||
|
|
74e05ba3a1 | ||
|
|
e77a3946d7 | ||
|
|
bcf04b1a6c | ||
|
|
d8844ab13c | ||
|
|
2e63787b96 | ||
|
|
de19a42b8b | ||
|
|
da07b35a96 | ||
|
|
9694ba4fd1 | ||
|
|
3644760f19 | ||
|
|
b89576ff7d | ||
|
|
d4b4385596 | ||
|
|
b8eb27d276 | ||
|
|
a63b8b372f | ||
|
|
380b7d1bcd | ||
|
|
5f14b9b0ae | ||
|
|
746c51901d | ||
|
|
439e7d4535 | ||
|
|
8abb0005f6 | ||
|
|
c8f4647373 | ||
|
|
5c47073518 | ||
|
|
fd1461cc98 | ||
|
|
a25c167d23 |
@@ -12,6 +12,13 @@ cache:
|
|||||||
- $HOME/google-cloud-sdk/
|
- $HOME/google-cloud-sdk/
|
||||||
- $HOME/k8scli
|
- $HOME/k8scli
|
||||||
|
|
||||||
|
services:
|
||||||
|
- docker
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- sudo apt-get update
|
||||||
|
- sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- go get github.com/Masterminds/glide
|
- go get github.com/Masterminds/glide
|
||||||
- hack/travis-kube-setup.sh
|
- hack/travis-kube-setup.sh
|
||||||
|
|||||||
+2
-5
@@ -38,13 +38,10 @@ minikube and its built-in docker daemon:
|
|||||||
$ docker build -t minikube/fission-bundle .
|
$ docker build -t minikube/fission-bundle .
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, install fission on your kubernetes cluster:
|
Next, install fission with this image on your kubernetes cluster using the helm chart:
|
||||||
|
|
||||||
```
|
```
|
||||||
# To install, update fission.yaml to point to the image you just made: "minikube/fission-bundle"
|
$ helm install --set "image=minikube/fission-bundle,pullPolicy=IfNotPresent,analytics=false" charts/fission-all
|
||||||
$ $EDITOR fission.yaml
|
|
||||||
$ kubectl create -f fission.yaml
|
|
||||||
$ kubectl create -f fission-nodeport.yaml
|
|
||||||
```
|
```
|
||||||
|
|
||||||
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:
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ Language-neutral components:
|
|||||||
|
|
||||||
Language-specific components:
|
Language-specific components:
|
||||||
|
|
||||||
* Environment container
|
* Environment container(s)
|
||||||
|
|
||||||
|
|
||||||
Controller
|
Controller
|
||||||
@@ -112,13 +112,13 @@ Environment Container
|
|||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
Environment containers run user-defined functions. Environment
|
Environment containers run user-defined functions. Environment
|
||||||
containers are language specific. They must contain an HTTP server
|
containers are language specific. Each environment container must
|
||||||
and a loader for functions.
|
contain an HTTP server and a loader for functions.
|
||||||
|
|
||||||
Poolmgr deploys the environment container into a pod with fetcher
|
Poolmgr deploys the environment container into a pod with fetcher
|
||||||
(fetcher is a simple utility that can fetch an HTTP url to a file at a
|
(fetcher is a simple utility that can fetch an HTTP url to a file at a
|
||||||
configured location). This pod forms a "generic pod", because it can
|
configured location). This pod forms a "generic pod", because it can
|
||||||
be loaded with any function.
|
be loaded with any function in that language.
|
||||||
|
|
||||||
When poolmgr needs to create a service for a function, it calls
|
When poolmgr needs to create a service for a function, it calls
|
||||||
fetcher to fetch the function. Fetcher downloads the function into a
|
fetcher to fetch the function. Fetcher downloads the function into a
|
||||||
@@ -134,7 +134,7 @@ Following is a diagram describe how log service works:
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
1. Pool manager choose a pod from pool to execute user function
|
1. Pool manager chooses a pod from the pool to execute user function
|
||||||
2. Pool manager makes a HTTP POST to logger helper, once helper receives
|
2. Pool manager makes a HTTP POST to logger helper, once helper receives
|
||||||
the request it creates a symlink to container log for fluentd.
|
the request it creates a symlink to container log for fluentd.
|
||||||
3. Fluentd reads log from symlink and pipes to influxdb
|
3. Fluentd reads log from symlink and pipes to influxdb
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
## Fission API ([area-api](https://github.com/fission/fission/labels/area-api))
|
## Fission API ([area-api](https://github.com/fission/fission/labels/area-api))
|
||||||
|
|
||||||
- TPR-based controller
|
- CRD-based controller
|
||||||
- API authentication
|
- API authentication
|
||||||
- Aggregated API server
|
- Aggregated API server
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
baseURL = "http://fission.io/docs/v0.2.1"
|
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"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
## Fission Documentation
|
## Fission Documentation
|
||||||
|
|
||||||
|
* [Installation guide](install)
|
||||||
|
|
||||||
|
* [Upgrade guide for v0.3 to v0.4](upgrade-from-v0.3)
|
||||||
[Installation guide](install)
|
|
||||||
[Upgrade guide](upgrade-from-v0.1)
|
|
||||||
@@ -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.1/fission-all-0.4.1.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.1/fission-all-0.4.1.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.1/fission-core-0.4.1.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.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.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.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
|
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.1/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.1
|
||||||
|
|
||||||
$ 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
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
---
|
||||||
|
title: "Upgrading from Fission v0.3 to v0.4.x"
|
||||||
|
date: 2017-11-04T03:38:29+08:00
|
||||||
|
draft: false
|
||||||
|
---
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
Kubernetes ThirdPartyResources ("TPR") are replaced by
|
||||||
|
CustomResourceDefinitions ("CRD"). TPRs have been deprecated and are
|
||||||
|
removed in Kubernetes 1.8.
|
||||||
|
|
||||||
|
Since Fission stores state in TPRs, we need to migrate this state from
|
||||||
|
TPRs to CRDs while upgrading.
|
||||||
|
|
||||||
|
Follow the instructions below if you're upgrading a Fission 0.2.1 or
|
||||||
|
0.3.0 cluster to 0.4. If you're using a pre-0.2 Fission cluster, use
|
||||||
|
the [upgrade guide from 0.1 to 0.2]() and then upgrade to 0.4.0.
|
||||||
|
|
||||||
|
## How to Upgrade
|
||||||
|
|
||||||
|
1. Get the 0.4.0 CLI
|
||||||
|
2. Get the Fission state from v0.3 install
|
||||||
|
3. Upgrade to Fission 0.4.0
|
||||||
|
4. Upgrade Kubernetes cluster version to 1.7.x or higher
|
||||||
|
5. Remove all TPR definition (for Kubernetes 1.7.x)
|
||||||
|
6. Restore Fission state into CRDs
|
||||||
|
|
||||||
|
### Get the new CLI
|
||||||
|
|
||||||
|
#### OS X
|
||||||
|
|
||||||
|
```
|
||||||
|
$ 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
|
||||||
|
|
||||||
|
```
|
||||||
|
$ 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
|
||||||
|
|
||||||
|
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/fission-cli-windows.exe)
|
||||||
|
|
||||||
|
### Get Fission state from v0.3 install
|
||||||
|
|
||||||
|
```
|
||||||
|
fission --server <your v0.3 server> tpr2crd dump --file state.json
|
||||||
|
```
|
||||||
|
|
||||||
|
You can skip the --server argument if you have the environment
|
||||||
|
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
|
||||||
|
current directory.
|
||||||
|
|
||||||
|
### Upgrade to Fission 0.4.0
|
||||||
|
|
||||||
|
Upgrade fission with a command similar to this:
|
||||||
|
|
||||||
|
```
|
||||||
|
helm upgrade fission-all --namespace fission
|
||||||
|
```
|
||||||
|
|
||||||
|
### Upgrade Kubernetes cluster version
|
||||||
|
|
||||||
|
Since CustomResource is only supported on Kubernetes v1.7+ and higher, please make sure
|
||||||
|
that you upgrade to the right version that supports CustomResource.
|
||||||
|
|
||||||
|
### Remove all TPR definition (for Kubernetes 1.7.x)
|
||||||
|
|
||||||
|
** NOTICE **: This step will remove TPR definition from your kubernetes cluster. Please make sure that you dump all TPRs at the second step!
|
||||||
|
|
||||||
|
Though Kubernetes will migrate TPRs to CRDs automatically when TPR definition is deleted if the same name CRD exists. We still need to make sure that there is no resource gets lost during the migration. Also, since we changed the capitalization of some CRDs to CamelCase (e.g. Httptrigger -> HTTPTrigger), we need to recreate those resources by ourselves.
|
||||||
|
|
||||||
|
```
|
||||||
|
fission tpr2crd delete
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restore your Fission state into Fission 0.4.0
|
||||||
|
|
||||||
|
```
|
||||||
|
fission tpr2crd restore --file state.json
|
||||||
|
```
|
||||||
|
|
||||||
|
This commands needs `$FISSION_URL` set to point to new fission installation.
|
||||||
|
|
||||||
|
It uses the file created in the first step. It doesn't modify state.json.
|
||||||
|
|
||||||
|
(Note that you can run this restore on any cluster; it doesn't have the be the same kubernetes
|
||||||
|
cluster as your old install.)
|
||||||
|
|
||||||
|
### Verify
|
||||||
|
|
||||||
|
Let's check the migration result, first run following command to check CRD established state.
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl get crd -o 'custom-columns=NAME:{.metadata.name},ESTABLISHED:{.status.conditions[?(@.type=="Established")].status}'
|
||||||
|
```
|
||||||
|
|
||||||
|
The output should be like this
|
||||||
|
|
||||||
|
```
|
||||||
|
NAME ESTABLISHED
|
||||||
|
environments.fission.io True
|
||||||
|
functions.fission.io True
|
||||||
|
httptriggers.fission.io True
|
||||||
|
kuberneteswatchtriggers.fission.io True
|
||||||
|
messagequeuetriggers.fission.io True
|
||||||
|
packages.fission.io True
|
||||||
|
timetriggers.fission.io True
|
||||||
|
```
|
||||||
|
|
||||||
|
And check that CRD resources you expect are there.
|
||||||
|
|
||||||
|
```
|
||||||
|
COMMAND:
|
||||||
|
fission [resource] list
|
||||||
|
|
||||||
|
RESOURCES:
|
||||||
|
environments
|
||||||
|
functions
|
||||||
|
httptriggers
|
||||||
|
kuberneteswatchtriggers
|
||||||
|
messagequeuetriggers
|
||||||
|
packages
|
||||||
|
timetriggers
|
||||||
|
```
|
||||||
@@ -45,8 +45,24 @@ A _function_ is a piece of code that follows the fission function
|
|||||||
interface.
|
interface.
|
||||||
|
|
||||||
An _environment_ contains the language- and runtime-specific parts of
|
An _environment_ contains the language- and runtime-specific parts of
|
||||||
running a function. Fission comes with NodeJS and Python
|
running a function.
|
||||||
environments; you can also extend environments or create entirely new
|
|
||||||
|
The following environments are currently available:
|
||||||
|
|
||||||
|
| Environment | Image |
|
||||||
|
| ------------------------------------ | ------------------------- |
|
||||||
|
| Binary (for executables or scripts) | `fission/binary-env` |
|
||||||
|
| Go | `fission/go-env` |
|
||||||
|
| .NET | `fission/dotnet-env` |
|
||||||
|
| .NET 2.0 | `fission/dotnet20-env` |
|
||||||
|
| NodeJS (Alpine) | `fission/node-env` |
|
||||||
|
| NodeJS (Debian) | `fission/node-env-debian` |
|
||||||
|
| Perl | `fission/perl-env` |
|
||||||
|
| PHP 7 | `fission/php-env` |
|
||||||
|
| Python 3 | `fission/python-env` |
|
||||||
|
| Ruby | `fission/ruby-env` |
|
||||||
|
|
||||||
|
You can also extend environments or create entirely new
|
||||||
ones if you want. (An environment is essentially just a container
|
ones if you want. (An environment is essentially just a container
|
||||||
with a webserver and dynamic loader.)
|
with a webserver and dynamic loader.)
|
||||||
|
|
||||||
@@ -81,7 +97,7 @@ See the [examples](examples) directory for more.
|
|||||||
Running Fission on your Cluster
|
Running Fission on your Cluster
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
See the [installation guide](http://fission.io/docs/v0.2.1/install/).
|
See the [installation guide](http://fission.io/docs/0.4.0/install/).
|
||||||
|
|
||||||
Compiling Fission
|
Compiling Fission
|
||||||
=================
|
=================
|
||||||
|
|||||||
+59
-19
@@ -21,11 +21,13 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -68,7 +70,9 @@ func MakeBuilder(sharedVolumePath string) *Builder {
|
|||||||
|
|
||||||
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" {
|
||||||
http.Error(w, "", 405)
|
e := fmt.Sprintf("Method not allowed: %v", r.Method)
|
||||||
|
log.Println(e)
|
||||||
|
builder.reply(w, "", e, http.StatusMethodNotAllowed)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,15 +85,17 @@ func (builder *Builder) Handler(w http.ResponseWriter, r *http.Request) {
|
|||||||
// parse request
|
// parse request
|
||||||
body, err := ioutil.ReadAll(r.Body)
|
body, err := ioutil.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error reading request body")
|
e := errors.New(fmt.Sprintf("Error reading request body: %v", err))
|
||||||
http.Error(w, err.Error(), 500)
|
log.Println(e.Error())
|
||||||
|
builder.reply(w, "", e.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var req PackageBuildRequest
|
var req PackageBuildRequest
|
||||||
err = json.Unmarshal(body, &req)
|
err = json.Unmarshal(body, &req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error parsing json body: %v", err)
|
e := errors.New(fmt.Sprintf("Error parsing json body: %v", err))
|
||||||
http.Error(w, err.Error(), 400)
|
log.Println(e.Error())
|
||||||
|
builder.reply(w, "", e.Error(), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Printf("Builder received request: %v", req)
|
log.Printf("Builder received request: %v", req)
|
||||||
@@ -106,66 +112,100 @@ func (builder *Builder) Handler(w http.ResponseWriter, r *http.Request) {
|
|||||||
buildLogs, err := builder.build(buildCmd, srcPkgPath, deployPkgPath)
|
buildLogs, err := builder.build(buildCmd, srcPkgPath, deployPkgPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e := errors.New(fmt.Sprintf("Error building source package: %v", err))
|
e := errors.New(fmt.Sprintf("Error building source package: %v", err))
|
||||||
http.Error(w, e.Error(), 500)
|
log.Println(e.Error())
|
||||||
|
// append error at the end of build logs
|
||||||
|
buildLogs += fmt.Sprintf("%v\n", e.Error())
|
||||||
|
builder.reply(w, deployPkgFilename, buildLogs, http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
builder.reply(w, deployPkgFilename, buildLogs, http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (builder *Builder) reply(w http.ResponseWriter, pkgFilename string, buildLogs string, statusCode int) {
|
||||||
resp := PackageBuildResponse{
|
resp := PackageBuildResponse{
|
||||||
ArtifactFilename: deployPkgFilename,
|
ArtifactFilename: pkgFilename,
|
||||||
BuildLogs: buildLogs,
|
BuildLogs: buildLogs,
|
||||||
}
|
}
|
||||||
|
|
||||||
rBody, err := json.Marshal(resp)
|
rBody, err := json.Marshal(resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e := errors.New(fmt.Sprintf("Error encoding response body: %v", err))
|
e := errors.New(fmt.Sprintf("Error encoding response body: %v", err))
|
||||||
http.Error(w, e.Error(), 500)
|
rBody = []byte(fmt.Sprintf(`{"buildLogs": "%v"}`, e.Error()))
|
||||||
return
|
statusCode = http.StatusInternalServerError
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Add("Content-Type", "application/json")
|
w.Header().Add("Content-Type", "application/json")
|
||||||
|
// should write header before writing the body,
|
||||||
|
// or client will receive HTTP 200 regardless the real status code
|
||||||
|
w.WriteHeader(statusCode)
|
||||||
w.Write(rBody)
|
w.Write(rBody)
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (builder *Builder) build(command string, srcPkgPath string, deployPkgPath string) (string, error) {
|
func (builder *Builder) build(command string, srcPkgPath string, deployPkgPath string) (string, error) {
|
||||||
cmd := exec.Command(command)
|
cmd := exec.Command(command)
|
||||||
cmd.Dir = srcPkgPath
|
|
||||||
|
fi, err := os.Stat(srcPkgPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.New(fmt.Sprintf("could not find srcPkgPath: '%s'", srcPkgPath))
|
||||||
|
}
|
||||||
|
if fi.IsDir() {
|
||||||
|
cmd.Dir = srcPkgPath
|
||||||
|
} else {
|
||||||
|
cmd.Dir = path.Dir(srcPkgPath)
|
||||||
|
}
|
||||||
|
|
||||||
// set env variables for build command
|
// set env variables for build command
|
||||||
cmd.Env = append(os.Environ(),
|
cmd.Env = append(os.Environ(),
|
||||||
fmt.Sprintf("%v=%v", envSrcPkg, srcPkgPath),
|
fmt.Sprintf("%v=%v", envSrcPkg, srcPkgPath),
|
||||||
fmt.Sprintf("%v=%v", envDeployPkg, deployPkgPath),
|
fmt.Sprintf("%v=%v", envDeployPkg, deployPkgPath),
|
||||||
)
|
)
|
||||||
|
|
||||||
cmdReader, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.New(fmt.Sprintf("Error creating stdout pipe for cmd: %v", err.Error()))
|
return "", errors.New(fmt.Sprintf("Error creating stdout pipe for cmd: %v", err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
scanner := bufio.NewScanner(cmdReader)
|
stderr, err := cmd.StderrPipe()
|
||||||
|
if err != nil {
|
||||||
|
return "", errors.New(fmt.Sprintf("Error creating stderr pipe for cmd: %v", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
var buildLogs string
|
||||||
|
|
||||||
|
fmt.Println("\n=== Build Logs ===")
|
||||||
|
// Init logs
|
||||||
|
fmt.Printf("command=%v\n", command)
|
||||||
|
fmt.Printf("env=%v\n", cmd.Env)
|
||||||
|
|
||||||
|
out := io.MultiReader(stdout, stderr)
|
||||||
|
scanner := bufio.NewScanner(out)
|
||||||
|
|
||||||
err = cmd.Start()
|
err = cmd.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.New(fmt.Sprintf("Error starting cmd: %v", err.Error()))
|
return "", errors.New(fmt.Sprintf("Error starting cmd: %v", err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
var buildLogs string
|
// Runtime logs
|
||||||
|
|
||||||
fmt.Println("\n=== Build Logs ===")
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
output := scanner.Text()
|
output := scanner.Text()
|
||||||
fmt.Println(output)
|
fmt.Println(output)
|
||||||
buildLogs += fmt.Sprintf("%v\n", output)
|
buildLogs += fmt.Sprintf("%v\n", output)
|
||||||
}
|
}
|
||||||
fmt.Println("==================\n")
|
|
||||||
|
|
||||||
if err := scanner.Err(); err != nil {
|
if err := scanner.Err(); err != nil {
|
||||||
return "", errors.New(fmt.Sprintf("Error reading cmd output: %v", err.Error()))
|
scanErr := errors.New(fmt.Sprintf("Error reading cmd output: %v", err.Error()))
|
||||||
|
fmt.Println(scanErr)
|
||||||
|
return buildLogs, scanErr
|
||||||
}
|
}
|
||||||
|
|
||||||
err = cmd.Wait()
|
err = cmd.Wait()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.New(fmt.Sprintf("Error waiting for cmd: %v", err.Error()))
|
cmdErr := errors.New(fmt.Sprintf("Error waiting for cmd '%v': %v", command, err.Error()))
|
||||||
|
fmt.Println(cmdErr)
|
||||||
|
return buildLogs, cmdErr
|
||||||
}
|
}
|
||||||
|
fmt.Println("==================\n")
|
||||||
|
|
||||||
return buildLogs, nil
|
return buildLogs, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -50,20 +51,18 @@ func (c *Client) Build(req *builder.PackageBuildRequest) (*builder.PackageBuildR
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
|
||||||
return nil, fission.MakeErrorFromHTTP(resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
rBody, err := ioutil.ReadAll(resp.Body)
|
rBody, err := ioutil.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("Error reading resp body: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pkgBuildResp := builder.PackageBuildResponse{}
|
pkgBuildResp := builder.PackageBuildResponse{}
|
||||||
err = json.Unmarshal([]byte(rBody), &pkgBuildResp)
|
err = json.Unmarshal([]byte(rBody), &pkgBuildResp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Printf("Error parsing resp body: %v", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &pkgBuildResp, nil
|
return &pkgBuildResp, fission.MakeErrorFromHTTP(resp)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
FROM alpine:3.5
|
||||||
|
|
||||||
|
RUN apk update
|
||||||
|
# Install some utility libraries for builders extending image
|
||||||
|
RUN apk add coreutils binutils findutils grep
|
||||||
|
|
||||||
|
ADD builder /builder
|
||||||
|
|
||||||
|
EXPOSE 8001
|
||||||
+24
-17
@@ -26,41 +26,39 @@ import (
|
|||||||
|
|
||||||
"github.com/gorilla/handlers"
|
"github.com/gorilla/handlers"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"k8s.io/client-go/1.5/kubernetes"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
BuildRequest struct {
|
BuildRequest struct {
|
||||||
Package api.ObjectMeta `json:"package"`
|
Package metav1.ObjectMeta `json:"package"`
|
||||||
}
|
}
|
||||||
|
|
||||||
BuilderMgr struct {
|
BuilderMgr struct {
|
||||||
fissionClient *tpr.FissionClient
|
fissionClient *crd.FissionClient
|
||||||
kubernetesClient *kubernetes.Clientset
|
storageSvcUrl string
|
||||||
storageSvcUrl string
|
namespace string
|
||||||
namespace string
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func MakeBuilderMgr(fissionClient *tpr.FissionClient,
|
func MakeBuilderMgr(fissionClient *crd.FissionClient,
|
||||||
kubernetesClient *kubernetes.Clientset, storageSvcUrl string,
|
kubernetesClient *kubernetes.Clientset, storageSvcUrl string,
|
||||||
envBuilderNamespace string) *BuilderMgr {
|
envBuilderNamespace string) *BuilderMgr {
|
||||||
|
|
||||||
envWatcher := makeEnvironmentWatcher(fissionClient, kubernetesClient, envBuilderNamespace)
|
envWatcher := makeEnvironmentWatcher(fissionClient, kubernetesClient, envBuilderNamespace)
|
||||||
go envWatcher.watchEnvironments()
|
go envWatcher.watchEnvironments()
|
||||||
|
|
||||||
pkgWatcher := makePackageWatcher(fissionClient, kubernetesClient, envBuilderNamespace, storageSvcUrl)
|
pkgWatcher := makePackageWatcher(fissionClient, envBuilderNamespace, storageSvcUrl)
|
||||||
go pkgWatcher.watchPackages()
|
go pkgWatcher.watchPackages()
|
||||||
|
|
||||||
return &BuilderMgr{
|
return &BuilderMgr{
|
||||||
fissionClient: fissionClient,
|
fissionClient: fissionClient,
|
||||||
kubernetesClient: kubernetesClient,
|
storageSvcUrl: storageSvcUrl,
|
||||||
storageSvcUrl: storageSvcUrl,
|
namespace: envBuilderNamespace,
|
||||||
namespace: envBuilderNamespace,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,14 +74,23 @@ func (builderMgr *BuilderMgr) build(w http.ResponseWriter, r *http.Request) {
|
|||||||
buildReq := BuildRequest{}
|
buildReq := BuildRequest{}
|
||||||
err = json.Unmarshal([]byte(body), &buildReq)
|
err = json.Unmarshal([]byte(body), &buildReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e := fmt.Sprintf("invalid request body: %v", err)
|
e := fmt.Sprintf("Invalid request body: %v", err)
|
||||||
log.Println(e)
|
log.Println(e)
|
||||||
http.Error(w, e, 400)
|
http.Error(w, e, 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
buildLogs, err := buildPackage(builderMgr.fissionClient, builderMgr.kubernetesClient,
|
pkg, err := builderMgr.fissionClient.
|
||||||
builderMgr.namespace, builderMgr.storageSvcUrl, buildReq)
|
Packages(buildReq.Package.Namespace).
|
||||||
|
Get(buildReq.Package.Name)
|
||||||
|
if err != nil {
|
||||||
|
e := fmt.Sprintf("Error getting package CRD info: %v", err)
|
||||||
|
log.Println(e)
|
||||||
|
http.Error(w, e, 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
buildLogs, err := buildPackage(builderMgr.fissionClient, builderMgr.namespace, builderMgr.storageSvcUrl, pkg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
code, e := fission.GetHTTPError(err)
|
code, e := fission.GetHTTPError(err)
|
||||||
http.Error(w, e, code)
|
http.Error(w, e, code)
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ package buildermgr
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Start the buildermgr service.
|
// Start the buildermgr service.
|
||||||
func Start(port int, storageSvcUrl string, envBuilderNamespace string) error {
|
func Start(port int, storageSvcUrl string, envBuilderNamespace string) error {
|
||||||
fissionClient, kubernetesClient, err := tpr.MakeFissionClient()
|
fissionClient, kubernetesClient, _, err := crd.MakeFissionClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to get kubernetes client: %v", err)
|
log.Printf("Failed to get kubernetes client: %v", err)
|
||||||
return err
|
return err
|
||||||
|
|||||||
+52
-46
@@ -19,18 +19,18 @@ package buildermgr
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/kubernetes"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
|
||||||
|
|
||||||
"github.com/dchest/uniuri"
|
"github.com/dchest/uniuri"
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/builder"
|
"github.com/fission/fission/builder"
|
||||||
builderClient "github.com/fission/fission/builder/client"
|
builderClient "github.com/fission/fission/builder/client"
|
||||||
|
"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/tpr"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// buildPackage helps to build source package into deployment package.
|
// buildPackage helps to build source package into deployment package.
|
||||||
@@ -43,41 +43,39 @@ import (
|
|||||||
// 6. Update package status to succeed state
|
// 6. Update package status to succeed state
|
||||||
// 7. Update package resource in package ref of functions that share the same package
|
// 7. Update package resource in package ref of functions that share the same package
|
||||||
// *. Update package status to failed state,if any one of steps above failed
|
// *. Update package status to failed state,if any one of steps above failed
|
||||||
func buildPackage(fissionClient *tpr.FissionClient, kubernetesClient *kubernetes.Clientset,
|
func buildPackage(fissionClient *crd.FissionClient, builderNamespace string,
|
||||||
builderNamespace string, storageSvcUrl string, buildReq BuildRequest) (buildLogs string, err error) {
|
storageSvcUrl string, pkg *crd.Package) (buildLogs string, err error) {
|
||||||
|
|
||||||
pkg, err := fissionClient.Packages(
|
|
||||||
buildReq.Package.Namespace).Get(buildReq.Package.Name)
|
|
||||||
if err != nil {
|
|
||||||
e := fmt.Sprintf("Error getting function TPR info: %v", err)
|
|
||||||
log.Println(e)
|
|
||||||
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, e, nil)
|
|
||||||
return e, fission.MakeError(500, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only do build for pending packages
|
// Only do build for pending packages
|
||||||
if pkg.Status.BuildStatus != fission.BuildStatusPending {
|
if pkg.Status.BuildStatus != fission.BuildStatusPending {
|
||||||
e := "package is not in pending state"
|
e := "package is not in pending state"
|
||||||
log.Println(e)
|
log.Println(e)
|
||||||
return e, fission.MakeError(400, e)
|
return e, fission.MakeError(http.StatusBadRequest, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
// update package status to running state, so that
|
// update package status to running state, so that
|
||||||
// we can know what status a package is through cli.
|
// we can know what status a package is through cli.
|
||||||
_, err = updatePackage(fissionClient, pkg, fission.BuildStatusRunning, "", nil)
|
newPkgRV, err := updatePackage(fissionClient, pkg, fission.BuildStatusRunning, "", nil)
|
||||||
|
|
||||||
|
// Kubernetes checks resource version before applying
|
||||||
|
// new resource config. The update operation will be
|
||||||
|
// rejected if the resource version in metadata is lower
|
||||||
|
// than the latest version. Set resource version with
|
||||||
|
// latest return from updatePackage.
|
||||||
|
pkg.Metadata.ResourceVersion = newPkgRV
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e := fmt.Sprintf("Error setting package pending state: %v", err)
|
e := fmt.Sprintf("Error setting package pending state: %v", err)
|
||||||
log.Println(e)
|
log.Println(e)
|
||||||
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, e, nil)
|
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, e, nil)
|
||||||
return e, fission.MakeError(500, e)
|
return e, fission.MakeError(http.StatusInternalServerError, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
env, err := fissionClient.Environments(api.NamespaceDefault).Get(pkg.Spec.Environment.Name)
|
env, err := fissionClient.Environments(metav1.NamespaceDefault).Get(pkg.Spec.Environment.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e := fmt.Sprintf("Error getting environment TPR info: %v", err)
|
e := fmt.Sprintf("Error getting environment CRD info: %v", err)
|
||||||
log.Println(e)
|
log.Println(e)
|
||||||
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, e, nil)
|
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, e, nil)
|
||||||
return e, fission.MakeError(500, e)
|
return e, fission.MakeError(http.StatusInternalServerError, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
svcName := fmt.Sprintf("%v-%v.%v", env.Metadata.Name, env.Metadata.ResourceVersion, builderNamespace)
|
svcName := fmt.Sprintf("%v-%v.%v", env.Metadata.Name, env.Metadata.ResourceVersion, builderNamespace)
|
||||||
@@ -97,12 +95,17 @@ func buildPackage(fissionClient *tpr.FissionClient, kubernetesClient *kubernetes
|
|||||||
e := fmt.Sprintf("Error fetching source package: %v", err)
|
e := fmt.Sprintf("Error fetching source package: %v", err)
|
||||||
log.Println(e)
|
log.Println(e)
|
||||||
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, e, nil)
|
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, e, nil)
|
||||||
return e, fission.MakeError(500, e)
|
return e, fission.MakeError(http.StatusInternalServerError, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
buildCmd := pkg.Spec.BuildCommand
|
||||||
|
if len(buildCmd) == 0 {
|
||||||
|
buildCmd = env.Spec.Builder.Command
|
||||||
}
|
}
|
||||||
|
|
||||||
pkgBuildReq := &builder.PackageBuildRequest{
|
pkgBuildReq := &builder.PackageBuildRequest{
|
||||||
SrcPkgFilename: srcPkgFilename,
|
SrcPkgFilename: srcPkgFilename,
|
||||||
BuildCommand: pkg.Spec.BuildCommand,
|
BuildCommand: buildCmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Start building with source package: %v", srcPkgFilename)
|
log.Printf("Start building with source package: %v", srcPkgFilename)
|
||||||
@@ -111,8 +114,13 @@ func buildPackage(fissionClient *tpr.FissionClient, kubernetesClient *kubernetes
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
e := fmt.Sprintf("Error building deployment package: %v", err)
|
e := fmt.Sprintf("Error building deployment package: %v", err)
|
||||||
log.Println(e)
|
log.Println(e)
|
||||||
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, e, nil)
|
var buildLogs string
|
||||||
return e, fission.MakeError(500, e)
|
if buildResp != nil {
|
||||||
|
buildLogs = buildResp.BuildLogs
|
||||||
|
}
|
||||||
|
buildLogs += fmt.Sprintf("%v\n", e)
|
||||||
|
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, buildLogs, nil)
|
||||||
|
return e, fission.MakeError(http.StatusInternalServerError, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Build succeed, source package: %v, deployment package: %v", srcPkgFilename, buildResp.ArtifactFilename)
|
log.Printf("Build succeed, source package: %v, deployment package: %v", srcPkgFilename, buildResp.ArtifactFilename)
|
||||||
@@ -128,28 +136,32 @@ func buildPackage(fissionClient *tpr.FissionClient, kubernetesClient *kubernetes
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
e := fmt.Sprintf("Error uploading deployment package: %v", err)
|
e := fmt.Sprintf("Error uploading deployment package: %v", err)
|
||||||
log.Println(e)
|
log.Println(e)
|
||||||
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, e, nil)
|
buildResp.BuildLogs += fmt.Sprintf("%v\n", e)
|
||||||
return e, fission.MakeError(500, e)
|
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, buildResp.BuildLogs, nil)
|
||||||
|
return e, fission.MakeError(http.StatusInternalServerError, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Start updating info of package: %v", pkg.Metadata.Name)
|
log.Printf("Start updating info of package: %v", pkg.Metadata.Name)
|
||||||
// update package status and also build logs
|
// update package status and also build logs
|
||||||
newPkgRV, err := updatePackage(fissionClient, pkg,
|
newPkgRV, err = updatePackage(fissionClient, pkg,
|
||||||
fission.BuildStatusSucceeded, buildResp.BuildLogs, uploadResp)
|
fission.BuildStatusSucceeded, buildResp.BuildLogs, uploadResp)
|
||||||
|
pkg.Metadata.ResourceVersion = newPkgRV
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e := fmt.Sprintf("Error creating deployment package TPR resource: %v", err)
|
e := fmt.Sprintf("Error creating deployment package CRD resource: %v", err)
|
||||||
log.Println(e)
|
log.Println(e)
|
||||||
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, e, nil)
|
buildResp.BuildLogs += fmt.Sprintf("%v\n", e)
|
||||||
return e, fission.MakeError(500, e)
|
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, buildResp.BuildLogs, nil)
|
||||||
|
return e, fission.MakeError(http.StatusInternalServerError, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
fnList, err := fissionClient.
|
fnList, err := fissionClient.
|
||||||
Functions(api.NamespaceDefault).List(api.ListOptions{})
|
Functions(metav1.NamespaceDefault).List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e := fmt.Sprintf("Error getting function list: %v", err)
|
e := fmt.Sprintf("Error getting function list: %v", err)
|
||||||
log.Println(e)
|
log.Println(e)
|
||||||
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, e, nil)
|
buildResp.BuildLogs += fmt.Sprintf("%v\n", e)
|
||||||
return e, fission.MakeError(500, e)
|
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, buildResp.BuildLogs, nil)
|
||||||
|
return e, fission.MakeError(http.StatusInternalServerError, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A package may be used by multiple functions. Update
|
// A package may be used by multiple functions. Update
|
||||||
@@ -159,13 +171,14 @@ func buildPackage(fissionClient *tpr.FissionClient, kubernetesClient *kubernetes
|
|||||||
fn.Spec.Package.PackageRef.Namespace == pkg.Metadata.Namespace &&
|
fn.Spec.Package.PackageRef.Namespace == pkg.Metadata.Namespace &&
|
||||||
fn.Spec.Package.PackageRef.ResourceVersion != pkg.Metadata.ResourceVersion {
|
fn.Spec.Package.PackageRef.ResourceVersion != pkg.Metadata.ResourceVersion {
|
||||||
fn.Spec.Package.PackageRef.ResourceVersion = newPkgRV
|
fn.Spec.Package.PackageRef.ResourceVersion = newPkgRV
|
||||||
// update TPR
|
// update CRD
|
||||||
_, err = fissionClient.Functions(fn.Metadata.Namespace).Update(&fn)
|
_, err = fissionClient.Functions(fn.Metadata.Namespace).Update(&fn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e := fmt.Sprintf("Error updating function package resource version: %v", err)
|
e := fmt.Sprintf("Error updating function package resource version: %v", err)
|
||||||
log.Println(e)
|
log.Println(e)
|
||||||
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, e, nil)
|
buildResp.BuildLogs += fmt.Sprintf("%v\n", e)
|
||||||
return e, fission.MakeError(500, e)
|
updatePackage(fissionClient, pkg, fission.BuildStatusFailed, buildResp.BuildLogs, nil)
|
||||||
|
return e, fission.MakeError(http.StatusInternalServerError, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,17 +188,10 @@ func buildPackage(fissionClient *tpr.FissionClient, kubernetesClient *kubernetes
|
|||||||
return buildResp.BuildLogs, nil
|
return buildResp.BuildLogs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func updatePackage(fissionClient *tpr.FissionClient,
|
func updatePackage(fissionClient *crd.FissionClient,
|
||||||
pkg *tpr.Package, status fission.BuildStatus, buildLogs string,
|
pkg *crd.Package, status fission.BuildStatus, buildLogs string,
|
||||||
uploadResp *fetcher.UploadResponse) (string, error) {
|
uploadResp *fetcher.UploadResponse) (string, error) {
|
||||||
|
|
||||||
// Kubernetes checks resource version before applying
|
|
||||||
// new resource config. The update operation will be
|
|
||||||
// rejected if the resource version in metadata is lower
|
|
||||||
// than the latest version. Set resource version empty
|
|
||||||
// string to skip resource version check.
|
|
||||||
pkg.Metadata.ResourceVersion = ""
|
|
||||||
|
|
||||||
pkg.Status = fission.PackageStatus{
|
pkg.Status = fission.PackageStatus{
|
||||||
BuildStatus: status,
|
BuildStatus: status,
|
||||||
BuildLog: buildLogs,
|
BuildLog: buildLogs,
|
||||||
@@ -200,7 +206,7 @@ func updatePackage(fissionClient *tpr.FissionClient,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update package spec
|
// update package spec
|
||||||
pkg, err := fissionClient.Packages(api.NamespaceDefault).Update(pkg)
|
pkg, err := fissionClient.Packages(metav1.NamespaceDefault).Update(pkg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error updating package: %v", err)
|
log.Printf("Error updating package: %v", err)
|
||||||
return "", err
|
return "", err
|
||||||
|
|||||||
+70
-60
@@ -22,15 +22,15 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/kubernetes"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/client-go/1.5/pkg/api/v1"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
"k8s.io/client-go/1.5/pkg/apis/extensions/v1beta1"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/client-go/1.5/pkg/labels"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/1.5/pkg/util/intstr"
|
apiv1 "k8s.io/client-go/pkg/api/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/watch"
|
"k8s.io/client-go/pkg/apis/extensions/v1beta1"
|
||||||
|
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
type requestType int
|
type requestType int
|
||||||
@@ -45,15 +45,15 @@ const (
|
|||||||
|
|
||||||
type (
|
type (
|
||||||
builderInfo struct {
|
builderInfo struct {
|
||||||
envMetadata *api.ObjectMeta
|
envMetadata *metav1.ObjectMeta
|
||||||
deployment *v1beta1.Deployment
|
deployment *v1beta1.Deployment
|
||||||
service *v1.Service
|
service *apiv1.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
envwRequest struct {
|
envwRequest struct {
|
||||||
requestType
|
requestType
|
||||||
env *tpr.Environment
|
env *crd.Environment
|
||||||
envList []tpr.Environment
|
envList []crd.Environment
|
||||||
respChan chan envwResponse
|
respChan chan envwResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,14 +66,14 @@ type (
|
|||||||
cache map[string]*builderInfo
|
cache map[string]*builderInfo
|
||||||
requestChan chan envwRequest
|
requestChan chan envwRequest
|
||||||
builderNamespace string
|
builderNamespace string
|
||||||
fissionClient *tpr.FissionClient
|
fissionClient *crd.FissionClient
|
||||||
kubernetesClient *kubernetes.Clientset
|
kubernetesClient *kubernetes.Clientset
|
||||||
fetcherImage string
|
fetcherImage string
|
||||||
fetcherImagePullPolicy v1.PullPolicy
|
fetcherImagePullPolicy apiv1.PullPolicy
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeEnvironmentWatcher(fissionClient *tpr.FissionClient,
|
func makeEnvironmentWatcher(fissionClient *crd.FissionClient,
|
||||||
kubernetesClient *kubernetes.Clientset, builderNamespace string) *environmentWatcher {
|
kubernetesClient *kubernetes.Clientset, builderNamespace string) *environmentWatcher {
|
||||||
|
|
||||||
fetcherImage := os.Getenv("FETCHER_IMAGE")
|
fetcherImage := os.Getenv("FETCHER_IMAGE")
|
||||||
@@ -86,14 +86,14 @@ func makeEnvironmentWatcher(fissionClient *tpr.FissionClient,
|
|||||||
fetcherImagePullPolicy = "IfNotPresent"
|
fetcherImagePullPolicy = "IfNotPresent"
|
||||||
}
|
}
|
||||||
|
|
||||||
var pullPolicy v1.PullPolicy
|
var pullPolicy apiv1.PullPolicy
|
||||||
switch fetcherImagePullPolicy {
|
switch fetcherImagePullPolicy {
|
||||||
case "Always":
|
case "Always":
|
||||||
pullPolicy = v1.PullAlways
|
pullPolicy = apiv1.PullAlways
|
||||||
case "Never":
|
case "Never":
|
||||||
pullPolicy = v1.PullNever
|
pullPolicy = apiv1.PullNever
|
||||||
default:
|
default:
|
||||||
pullPolicy = v1.PullIfNotPresent
|
pullPolicy = apiv1.PullIfNotPresent
|
||||||
}
|
}
|
||||||
|
|
||||||
envWatcher := &environmentWatcher{
|
envWatcher := &environmentWatcher{
|
||||||
@@ -125,7 +125,7 @@ func (envw *environmentWatcher) getLabels(envName string, envResourceVersion str
|
|||||||
func (envw *environmentWatcher) watchEnvironments() {
|
func (envw *environmentWatcher) watchEnvironments() {
|
||||||
rv := ""
|
rv := ""
|
||||||
for {
|
for {
|
||||||
wi, err := envw.fissionClient.Environments(api.NamespaceAll).Watch(api.ListOptions{
|
wi, err := envw.fissionClient.Environments(metav1.NamespaceAll).Watch(metav1.ListOptions{
|
||||||
ResourceVersion: rv,
|
ResourceVersion: rv,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -144,7 +144,7 @@ func (envw *environmentWatcher) watchEnvironments() {
|
|||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
env := ev.Object.(*tpr.Environment)
|
env := ev.Object.(*crd.Environment)
|
||||||
rv = env.Metadata.ResourceVersion
|
rv = env.Metadata.ResourceVersion
|
||||||
envw.sync()
|
envw.sync()
|
||||||
}
|
}
|
||||||
@@ -152,9 +152,9 @@ func (envw *environmentWatcher) watchEnvironments() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (envw *environmentWatcher) sync() {
|
func (envw *environmentWatcher) sync() {
|
||||||
envList, err := envw.fissionClient.Environments(api.NamespaceAll).List(api.ListOptions{})
|
envList, err := envw.fissionClient.Environments(metav1.NamespaceAll).List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error syncing environment TPR resources: %v", err)
|
log.Fatalf("Error syncing environment CRD resources: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create environment builders for all environments
|
// Create environment builders for all environments
|
||||||
@@ -191,7 +191,7 @@ func (envw *environmentWatcher) service() {
|
|||||||
req.respChan <- envwResponse{builderInfo: builderInfo}
|
req.respChan <- envwResponse{builderInfo: builderInfo}
|
||||||
|
|
||||||
case CLEANUP_BUILDERS:
|
case CLEANUP_BUILDERS:
|
||||||
latestEnvList := make(map[string]*tpr.Environment)
|
latestEnvList := make(map[string]*crd.Environment)
|
||||||
for i := range req.envList {
|
for i := range req.envList {
|
||||||
env := req.envList[i]
|
env := req.envList[i]
|
||||||
key := envw.getCacheKey(env.Metadata.Name, env.Metadata.ResourceVersion)
|
key := envw.getCacheKey(env.Metadata.Name, env.Metadata.ResourceVersion)
|
||||||
@@ -201,7 +201,7 @@ func (envw *environmentWatcher) service() {
|
|||||||
// If an environment is deleted when builder manager down,
|
// If an environment is deleted when builder manager down,
|
||||||
// the builder belongs to the environment will be out-of-
|
// the builder belongs to the environment will be out-of-
|
||||||
// control (an orphan builder) since there is no record in
|
// control (an orphan builder) since there is no record in
|
||||||
// cache and TPR. We need to iterate over the services &
|
// cache and CRD. We need to iterate over the services &
|
||||||
// deployments to remove both normal and orphan builders.
|
// deployments to remove both normal and orphan builders.
|
||||||
|
|
||||||
svcList, err := envw.getBuilderServiceList(nil)
|
svcList, err := envw.getBuilderServiceList(nil)
|
||||||
@@ -241,7 +241,7 @@ func (envw *environmentWatcher) service() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (envw *environmentWatcher) getEnvBuilder(env *tpr.Environment) (*builderInfo, error) {
|
func (envw *environmentWatcher) getEnvBuilder(env *crd.Environment) (*builderInfo, error) {
|
||||||
respChan := make(chan envwResponse)
|
respChan := make(chan envwResponse)
|
||||||
envw.requestChan <- envwRequest{
|
envw.requestChan <- envwRequest{
|
||||||
requestType: GET_BUILDER,
|
requestType: GET_BUILDER,
|
||||||
@@ -252,15 +252,15 @@ func (envw *environmentWatcher) getEnvBuilder(env *tpr.Environment) (*builderInf
|
|||||||
return resp.builderInfo, resp.err
|
return resp.builderInfo, resp.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (envw *environmentWatcher) cleanupEnvBuilders(envs []tpr.Environment) {
|
func (envw *environmentWatcher) cleanupEnvBuilders(envs []crd.Environment) {
|
||||||
envw.requestChan <- envwRequest{
|
envw.requestChan <- envwRequest{
|
||||||
requestType: CLEANUP_BUILDERS,
|
requestType: CLEANUP_BUILDERS,
|
||||||
envList: envs,
|
envList: envs,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (envw *environmentWatcher) createBuilder(env *tpr.Environment) (*builderInfo, error) {
|
func (envw *environmentWatcher) createBuilder(env *crd.Environment) (*builderInfo, error) {
|
||||||
var svc *v1.Service
|
var svc *apiv1.Service
|
||||||
var deploy *v1beta1.Deployment
|
var deploy *v1beta1.Deployment
|
||||||
|
|
||||||
sel := envw.getLabels(env.Metadata.Name, env.Metadata.ResourceVersion)
|
sel := envw.getLabels(env.Metadata.Name, env.Metadata.ResourceVersion)
|
||||||
@@ -269,22 +269,32 @@ func (envw *environmentWatcher) createBuilder(env *tpr.Environment) (*builderInf
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// there should be only one service in svcList
|
||||||
if len(svcList) == 0 {
|
if len(svcList) == 0 {
|
||||||
svc, err = envw.createBuilderService(env)
|
svc, err = envw.createBuilderService(env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error creating builder service: %v", err)
|
return nil, fmt.Errorf("Error creating builder service: %v", err)
|
||||||
}
|
}
|
||||||
|
} else if len(svcList) == 1 {
|
||||||
|
svc = &svcList[0]
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("Found more than one builder service for environment %v", env.Metadata.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
deployList, err := envw.getBuilderDeploymentList(sel)
|
deployList, err := envw.getBuilderDeploymentList(sel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// there should be only one deploy in deployList
|
||||||
if len(deployList) == 0 {
|
if len(deployList) == 0 {
|
||||||
deploy, err = envw.createBuilderDeployment(env)
|
deploy, err = envw.createBuilderDeployment(env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error creating builder deployment: %v", err)
|
return nil, fmt.Errorf("Error creating builder deployment: %v", err)
|
||||||
}
|
}
|
||||||
|
} else if len(deployList) == 1 {
|
||||||
|
deploy = &deployList[0]
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("Found more than one builder deployment for environment %v", env.Metadata.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &builderInfo{
|
return &builderInfo{
|
||||||
@@ -305,7 +315,7 @@ func (envw *environmentWatcher) deleteBuilderService(sel map[string]string) erro
|
|||||||
// cascading deletion
|
// cascading deletion
|
||||||
// https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/
|
// https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/
|
||||||
falseVal := false
|
falseVal := false
|
||||||
delOpt := &api.DeleteOptions{
|
delOpt := &metav1.DeleteOptions{
|
||||||
OrphanDependents: &falseVal,
|
OrphanDependents: &falseVal,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,11 +338,11 @@ func (envw *environmentWatcher) deleteBuilderDeployment(sel map[string]string) e
|
|||||||
log.Printf("Removing builder deployment: %v", deploy.ObjectMeta.Name)
|
log.Printf("Removing builder deployment: %v", deploy.ObjectMeta.Name)
|
||||||
|
|
||||||
falseVal := false
|
falseVal := false
|
||||||
delOpt := &api.DeleteOptions{
|
delOpt := &metav1.DeleteOptions{
|
||||||
OrphanDependents: &falseVal,
|
OrphanDependents: &falseVal,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = envw.kubernetesClient.
|
err = envw.kubernetesClient.ExtensionsV1beta1().
|
||||||
Deployments(envw.builderNamespace).
|
Deployments(envw.builderNamespace).
|
||||||
Delete(deploy.ObjectMeta.Name, delOpt)
|
Delete(deploy.ObjectMeta.Name, delOpt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -342,10 +352,10 @@ func (envw *environmentWatcher) deleteBuilderDeployment(sel map[string]string) e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (envw *environmentWatcher) getBuilderServiceList(sel map[string]string) ([]v1.Service, error) {
|
func (envw *environmentWatcher) getBuilderServiceList(sel map[string]string) ([]apiv1.Service, error) {
|
||||||
svcList, err := envw.kubernetesClient.Services(envw.builderNamespace).List(
|
svcList, err := envw.kubernetesClient.Services(envw.builderNamespace).List(
|
||||||
api.ListOptions{
|
metav1.ListOptions{
|
||||||
LabelSelector: labels.Set(sel).AsSelector(),
|
LabelSelector: labels.Set(sel).AsSelector().String(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error getting builder service list: %v", err)
|
return nil, fmt.Errorf("Error getting builder service list: %v", err)
|
||||||
@@ -353,22 +363,22 @@ func (envw *environmentWatcher) getBuilderServiceList(sel map[string]string) ([]
|
|||||||
return svcList.Items, nil
|
return svcList.Items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (envw *environmentWatcher) createBuilderService(env *tpr.Environment) (*v1.Service, error) {
|
func (envw *environmentWatcher) createBuilderService(env *crd.Environment) (*apiv1.Service, error) {
|
||||||
name := envw.getCacheKey(env.Metadata.Name, env.Metadata.ResourceVersion)
|
name := envw.getCacheKey(env.Metadata.Name, env.Metadata.ResourceVersion)
|
||||||
sel := envw.getLabels(env.Metadata.Name, env.Metadata.ResourceVersion)
|
sel := envw.getLabels(env.Metadata.Name, env.Metadata.ResourceVersion)
|
||||||
service := v1.Service{
|
service := apiv1.Service{
|
||||||
ObjectMeta: v1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Namespace: envw.builderNamespace,
|
Namespace: envw.builderNamespace,
|
||||||
Name: name,
|
Name: name,
|
||||||
Labels: sel,
|
Labels: sel,
|
||||||
},
|
},
|
||||||
Spec: v1.ServiceSpec{
|
Spec: apiv1.ServiceSpec{
|
||||||
Selector: sel,
|
Selector: sel,
|
||||||
Type: v1.ServiceTypeClusterIP,
|
Type: apiv1.ServiceTypeClusterIP,
|
||||||
Ports: []v1.ServicePort{
|
Ports: []apiv1.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "fetcher-port",
|
Name: "fetcher-port",
|
||||||
Protocol: v1.ProtocolTCP,
|
Protocol: apiv1.ProtocolTCP,
|
||||||
Port: 8000,
|
Port: 8000,
|
||||||
TargetPort: intstr.IntOrString{
|
TargetPort: intstr.IntOrString{
|
||||||
Type: intstr.Int,
|
Type: intstr.Int,
|
||||||
@@ -377,7 +387,7 @@ func (envw *environmentWatcher) createBuilderService(env *tpr.Environment) (*v1.
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "builder-port",
|
Name: "builder-port",
|
||||||
Protocol: v1.ProtocolTCP,
|
Protocol: apiv1.ProtocolTCP,
|
||||||
Port: 8001,
|
Port: 8001,
|
||||||
TargetPort: intstr.IntOrString{
|
TargetPort: intstr.IntOrString{
|
||||||
Type: intstr.Int,
|
Type: intstr.Int,
|
||||||
@@ -396,9 +406,9 @@ func (envw *environmentWatcher) createBuilderService(env *tpr.Environment) (*v1.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (envw *environmentWatcher) getBuilderDeploymentList(sel map[string]string) ([]v1beta1.Deployment, error) {
|
func (envw *environmentWatcher) getBuilderDeploymentList(sel map[string]string) ([]v1beta1.Deployment, error) {
|
||||||
deployList, err := envw.kubernetesClient.Deployments(envw.builderNamespace).List(
|
deployList, err := envw.kubernetesClient.ExtensionsV1beta1().Deployments(envw.builderNamespace).List(
|
||||||
api.ListOptions{
|
metav1.ListOptions{
|
||||||
LabelSelector: labels.Set(sel).AsSelector(),
|
LabelSelector: labels.Set(sel).AsSelector().String(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error getting builder deployment list: %v", err)
|
return nil, fmt.Errorf("Error getting builder deployment list: %v", err)
|
||||||
@@ -406,42 +416,42 @@ func (envw *environmentWatcher) getBuilderDeploymentList(sel map[string]string)
|
|||||||
return deployList.Items, nil
|
return deployList.Items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (envw *environmentWatcher) createBuilderDeployment(env *tpr.Environment) (*v1beta1.Deployment, error) {
|
func (envw *environmentWatcher) createBuilderDeployment(env *crd.Environment) (*v1beta1.Deployment, error) {
|
||||||
sharedMountPath := "/package"
|
sharedMountPath := "/package"
|
||||||
name := envw.getCacheKey(env.Metadata.Name, env.Metadata.ResourceVersion)
|
name := envw.getCacheKey(env.Metadata.Name, env.Metadata.ResourceVersion)
|
||||||
sel := envw.getLabels(env.Metadata.Name, env.Metadata.ResourceVersion)
|
sel := envw.getLabels(env.Metadata.Name, env.Metadata.ResourceVersion)
|
||||||
var replicas int32 = 1
|
var replicas int32 = 1
|
||||||
deployment := &v1beta1.Deployment{
|
deployment := &v1beta1.Deployment{
|
||||||
ObjectMeta: v1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Namespace: envw.builderNamespace,
|
Namespace: envw.builderNamespace,
|
||||||
Name: name,
|
Name: name,
|
||||||
Labels: sel,
|
Labels: sel,
|
||||||
},
|
},
|
||||||
Spec: v1beta1.DeploymentSpec{
|
Spec: v1beta1.DeploymentSpec{
|
||||||
Replicas: &replicas,
|
Replicas: &replicas,
|
||||||
Selector: &v1beta1.LabelSelector{
|
Selector: &metav1.LabelSelector{
|
||||||
MatchLabels: sel,
|
MatchLabels: sel,
|
||||||
},
|
},
|
||||||
Template: v1.PodTemplateSpec{
|
Template: apiv1.PodTemplateSpec{
|
||||||
ObjectMeta: v1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Labels: sel,
|
Labels: sel,
|
||||||
},
|
},
|
||||||
Spec: v1.PodSpec{
|
Spec: apiv1.PodSpec{
|
||||||
Volumes: []v1.Volume{
|
Volumes: []apiv1.Volume{
|
||||||
{
|
{
|
||||||
Name: "package",
|
Name: "package",
|
||||||
VolumeSource: v1.VolumeSource{
|
VolumeSource: apiv1.VolumeSource{
|
||||||
EmptyDir: &v1.EmptyDirVolumeSource{},
|
EmptyDir: &apiv1.EmptyDirVolumeSource{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Containers: []v1.Container{
|
Containers: []apiv1.Container{
|
||||||
{
|
{
|
||||||
Name: "builder",
|
Name: "builder",
|
||||||
Image: env.Spec.Builder.Image,
|
Image: env.Spec.Builder.Image,
|
||||||
ImagePullPolicy: v1.PullAlways,
|
ImagePullPolicy: apiv1.PullAlways,
|
||||||
TerminationMessagePath: "/dev/termination-log",
|
TerminationMessagePath: "/dev/termination-log",
|
||||||
VolumeMounts: []v1.VolumeMount{
|
VolumeMounts: []apiv1.VolumeMount{
|
||||||
{
|
{
|
||||||
Name: "package",
|
Name: "package",
|
||||||
MountPath: sharedMountPath,
|
MountPath: sharedMountPath,
|
||||||
@@ -454,7 +464,7 @@ func (envw *environmentWatcher) createBuilderDeployment(env *tpr.Environment) (*
|
|||||||
Image: envw.fetcherImage,
|
Image: envw.fetcherImage,
|
||||||
ImagePullPolicy: envw.fetcherImagePullPolicy,
|
ImagePullPolicy: envw.fetcherImagePullPolicy,
|
||||||
TerminationMessagePath: "/dev/termination-log",
|
TerminationMessagePath: "/dev/termination-log",
|
||||||
VolumeMounts: []v1.VolumeMount{
|
VolumeMounts: []apiv1.VolumeMount{
|
||||||
{
|
{
|
||||||
Name: "package",
|
Name: "package",
|
||||||
MountPath: sharedMountPath,
|
MountPath: sharedMountPath,
|
||||||
@@ -469,7 +479,7 @@ func (envw *environmentWatcher) createBuilderDeployment(env *tpr.Environment) (*
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
log.Printf("Creating builder deployment: %v", envw.getCacheKey(env.Metadata.Name, env.Metadata.ResourceVersion))
|
log.Printf("Creating builder deployment: %v", envw.getCacheKey(env.Metadata.Name, env.Metadata.ResourceVersion))
|
||||||
_, err := envw.kubernetesClient.Deployments(envw.builderNamespace).Create(deployment)
|
_, err := envw.kubernetesClient.ExtensionsV1beta1().Deployments(envw.builderNamespace).Create(deployment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-20
@@ -20,53 +20,46 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/kubernetes"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/client-go/1.5/pkg/watch"
|
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
packageWatcher struct {
|
packageWatcher struct {
|
||||||
fissionClient *tpr.FissionClient
|
fissionClient *crd.FissionClient
|
||||||
kubernetesClient *kubernetes.Clientset
|
|
||||||
builderNamespace string
|
builderNamespace string
|
||||||
storageSvcUrl string
|
storageSvcUrl string
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func makePackageWatcher(fissionClient *tpr.FissionClient,
|
func makePackageWatcher(fissionClient *crd.FissionClient,
|
||||||
kubernetesClient *kubernetes.Clientset, builderNamespace string, storageSvcUrl string) *packageWatcher {
|
builderNamespace string, storageSvcUrl string) *packageWatcher {
|
||||||
pkgw := &packageWatcher{
|
pkgw := &packageWatcher{
|
||||||
fissionClient: fissionClient,
|
fissionClient: fissionClient,
|
||||||
kubernetesClient: kubernetesClient,
|
|
||||||
builderNamespace: builderNamespace,
|
builderNamespace: builderNamespace,
|
||||||
storageSvcUrl: storageSvcUrl,
|
storageSvcUrl: storageSvcUrl,
|
||||||
}
|
}
|
||||||
return pkgw
|
return pkgw
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pkgw *packageWatcher) build(pkgMetadata api.ObjectMeta) {
|
func (pkgw *packageWatcher) build(pkg *crd.Package) {
|
||||||
buildReq := BuildRequest{
|
_, err := buildPackage(pkgw.fissionClient, pkgw.builderNamespace, pkgw.storageSvcUrl, pkg)
|
||||||
Package: pkgMetadata,
|
|
||||||
}
|
|
||||||
_, err := buildPackage(pkgw.fissionClient,
|
|
||||||
pkgw.kubernetesClient, pkgw.builderNamespace, pkgw.storageSvcUrl, buildReq)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error building package %v: %v", buildReq.Package.Name, err)
|
log.Printf("Error building package %v: %v", pkg.Metadata.Name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pkgw *packageWatcher) watchPackages() {
|
func (pkgw *packageWatcher) watchPackages() {
|
||||||
rv := ""
|
rv := ""
|
||||||
for {
|
for {
|
||||||
wi, err := pkgw.fissionClient.Packages(api.NamespaceDefault).Watch(api.ListOptions{
|
wi, err := pkgw.fissionClient.Packages(metav1.NamespaceDefault).Watch(metav1.ListOptions{
|
||||||
ResourceVersion: rv,
|
ResourceVersion: rv,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error watching package TPR resources: %v", err)
|
log.Fatalf("Error watching package CRD resources: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@@ -79,12 +72,12 @@ func (pkgw *packageWatcher) watchPackages() {
|
|||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
pkg := ev.Object.(*tpr.Package)
|
pkg := ev.Object.(*crd.Package)
|
||||||
rv = pkg.Metadata.ResourceVersion
|
rv = pkg.Metadata.ResourceVersion
|
||||||
|
|
||||||
// only do build for packages in pending state
|
// only do build for packages in pending state
|
||||||
if pkg.Status.BuildStatus == fission.BuildStatusPending {
|
if pkg.Status.BuildStatus == fission.BuildStatusPending {
|
||||||
go pkgw.build(pkg.Metadata)
|
go pkgw.build(pkg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- Kubernetes 1.6+ with Beta APIs enabled
|
- Kubernetes 1.8 or later
|
||||||
|
|
||||||
|
|
||||||
## Helm charts
|
## Helm charts
|
||||||
@@ -48,7 +48,6 @@ The following table lists the configurable parameters of the Fission chart and t
|
|||||||
| `routerPort` | Fission Router Service Port | `31314` |
|
| `routerPort` | Fission Router Service Port | `31314` |
|
||||||
| `functionNamespace` | Namespace for Fission functions | `fission-function` |
|
| `functionNamespace` | Namespace for Fission functions | `fission-function` |
|
||||||
| `builderNamespace` | Namespace for Fission environment builders | `fission-builder` |
|
| `builderNamespace` | Namespace for Fission environment builders | `fission-builder` |
|
||||||
| `openshift` | RBAC for openshift | `false` |
|
|
||||||
|
|
||||||
|
|
||||||
* Extra configuration for `fission-all`
|
* Extra configuration for `fission-all`
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
name: fission-all
|
name: fission-all
|
||||||
version: 0.3.0
|
version: 0.4.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.3.0
|
appVersion: 0.4.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.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.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.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.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.3.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.4.1/fission-cli-windows.exe
|
||||||
|
|
||||||
2. Set the FISSION_URL and FISSION_ROUTER environment variables.
|
2. Set the FISSION_URL and FISSION_ROUTER environment variables.
|
||||||
|
|
||||||
|
|||||||
@@ -1,77 +1,3 @@
|
|||||||
{{ if .Values.openshift }}
|
|
||||||
|
|
||||||
# For openshift
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ProjectRequest
|
|
||||||
metadata:
|
|
||||||
name: fission
|
|
||||||
labels:
|
|
||||||
name: fission
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ProjectRequest
|
|
||||||
metadata:
|
|
||||||
name: {{ .Values.functionNamespace }}
|
|
||||||
labels:
|
|
||||||
name: fission-function
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: fission-admin
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: fission:fission-admin
|
|
||||||
rules:
|
|
||||||
- apiGroups:
|
|
||||||
- extensions
|
|
||||||
attributeRestrictions: null
|
|
||||||
resources:
|
|
||||||
- deployments
|
|
||||||
verbs:
|
|
||||||
- create
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- update
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
attributeRestrictions: null
|
|
||||||
resources:
|
|
||||||
- pods
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- update
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
groupNames: null
|
|
||||||
kind: RoleBinding
|
|
||||||
metadata:
|
|
||||||
name: fission:fission-admin
|
|
||||||
namespace: {{ .Values.functionNamespace }}
|
|
||||||
roleRef:
|
|
||||||
name: fission:fission-admin
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: fission-admin
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
userNames:
|
|
||||||
- system:serviceaccount:fission:fission-admin
|
|
||||||
|
|
||||||
{{ else }}
|
|
||||||
|
|
||||||
# For all environments except openshift
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
@@ -131,7 +57,7 @@ roleRef:
|
|||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
metadata:
|
metadata:
|
||||||
name: fission-tpr
|
name: fission-crd
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: fission-svc
|
name: fission-svc
|
||||||
@@ -152,7 +78,7 @@ metadata:
|
|||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
metadata:
|
metadata:
|
||||||
name: fission-fetcher-tpr
|
name: fission-fetcher-crd
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: fission-fetcher
|
name: fission-fetcher
|
||||||
@@ -173,7 +99,7 @@ metadata:
|
|||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
metadata:
|
metadata:
|
||||||
name: fission-builder-tpr
|
name: fission-builder-crd
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: fission-builder
|
name: fission-builder
|
||||||
@@ -183,8 +109,6 @@ roleRef:
|
|||||||
name: cluster-admin
|
name: cluster-admin
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: extensions/v1beta1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
@@ -226,16 +150,16 @@ spec:
|
|||||||
image: "{{ .Values.image }}:{{ .Values.imageTag }}"
|
image: "{{ .Values.image }}:{{ .Values.imageTag }}"
|
||||||
imagePullPolicy: {{ .Values.pullPolicy }}
|
imagePullPolicy: {{ .Values.pullPolicy }}
|
||||||
command: ["/fission-bundle"]
|
command: ["/fission-bundle"]
|
||||||
args: ["--routerPort", "8888", "--poolmgrUrl", "http://poolmgr.{{ .Release.Namespace }}"]
|
args: ["--routerPort", "8888", "--executorUrl", "http://executor.{{ .Release.Namespace }}"]
|
||||||
serviceAccount: fission-svc
|
serviceAccount: fission-svc
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: poolmgr
|
name: executor
|
||||||
labels:
|
labels:
|
||||||
svc: poolmgr
|
svc: executor
|
||||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||||
spec:
|
spec:
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
@@ -243,13 +167,13 @@ spec:
|
|||||||
- port: 80
|
- port: 80
|
||||||
targetPort: 8888
|
targetPort: 8888
|
||||||
selector:
|
selector:
|
||||||
svc: poolmgr
|
svc: executor
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: extensions/v1beta1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: poolmgr
|
name: executor
|
||||||
labels:
|
labels:
|
||||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||||
spec:
|
spec:
|
||||||
@@ -257,14 +181,14 @@ spec:
|
|||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
svc: poolmgr
|
svc: executor
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: poolmgr
|
- name: executor
|
||||||
image: "{{ .Values.image }}:{{ .Values.imageTag }}"
|
image: "{{ .Values.image }}:{{ .Values.imageTag }}"
|
||||||
imagePullPolicy: {{ .Values.pullPolicy }}
|
imagePullPolicy: {{ .Values.pullPolicy }}
|
||||||
command: ["/fission-bundle"]
|
command: ["/fission-bundle"]
|
||||||
args: ["--poolmgrPort", "8888", "--namespace", "{{ .Values.functionNamespace }}", "--fission-namespace", "{{ .Release.Namespace }}"]
|
args: ["--executorPort", "8888", "--namespace", "{{ .Values.functionNamespace }}", "--fission-namespace", "{{ .Release.Namespace }}"]
|
||||||
env:
|
env:
|
||||||
- name: FETCHER_IMAGE
|
- name: FETCHER_IMAGE
|
||||||
value: "{{ .Values.fetcherImage }}:{{ .Values.fetcherImageTag }}"
|
value: "{{ .Values.fetcherImage }}:{{ .Values.fetcherImageTag }}"
|
||||||
@@ -273,7 +197,6 @@ spec:
|
|||||||
- name: RUNTIME_IMAGE_PULL_POLICY
|
- name: RUNTIME_IMAGE_PULL_POLICY
|
||||||
value: "{{ .Values.pullPolicy }}"
|
value: "{{ .Values.pullPolicy }}"
|
||||||
serviceAccount: fission-svc
|
serviceAccount: fission-svc
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
@@ -348,7 +271,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 +323,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 +343,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 +359,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
|
||||||
|
|||||||
@@ -7,17 +7,17 @@ metadata:
|
|||||||
app: fission-storage
|
app: fission-storage
|
||||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||||
release: "{{ .Release.Name }}"
|
release: "{{ .Release.Name }}"
|
||||||
annotations:
|
|
||||||
{{- if .Values.persistence.storageClass }}
|
|
||||||
volume.beta.kubernetes.io/storage-class: {{ .Values.persistence.storageClass | quote }}
|
|
||||||
{{- else }}
|
|
||||||
volume.alpha.kubernetes.io/storage-class: default
|
|
||||||
{{- end }}
|
|
||||||
spec:
|
spec:
|
||||||
accessModes:
|
accessModes:
|
||||||
- {{ .Values.persistence.accessMode | quote }}
|
- {{ .Values.persistence.accessMode | quote }}
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .Values.persistence.size | quote }}
|
storage: {{ .Values.persistence.size | quote }}
|
||||||
|
{{- if .Values.persistence.storageClass }}
|
||||||
|
{{- if (eq "-" .Values.persistence.storageClass) }}
|
||||||
|
storageClassName: ""
|
||||||
|
{{- else }}
|
||||||
|
storageClassName: {{ .Values.persistence.storageClass | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
# Fission chart configuration
|
# Fission chart configuration
|
||||||
#
|
#
|
||||||
|
|
||||||
## Kubernetes configuration
|
## Kubernetes configuration
|
||||||
## For minikube, set this to NodePort, elsewhere use LoadBalancer.
|
## For minikube, set this to NodePort, elsewhere use LoadBalancer.
|
||||||
@@ -13,13 +13,13 @@ image: fission/fission-bundle
|
|||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
## Fission image version
|
## Fission image version
|
||||||
imageTag: 0.3.0
|
imageTag: 0.4.1
|
||||||
|
|
||||||
## 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.1
|
||||||
|
|
||||||
## Port at which Fission controller service should be exposed
|
## Port at which Fission controller service should be exposed
|
||||||
controllerPort: 31313
|
controllerPort: 31313
|
||||||
@@ -38,9 +38,6 @@ functionNamespace: fission-function
|
|||||||
## the release namespace)
|
## the release namespace)
|
||||||
builderNamespace: fission-builder
|
builderNamespace: fission-builder
|
||||||
|
|
||||||
## Set up openshift RBAC rule
|
|
||||||
openshift: false
|
|
||||||
|
|
||||||
## Logger config
|
## Logger config
|
||||||
logger:
|
logger:
|
||||||
influxdbAdmin: "admin"
|
influxdbAdmin: "admin"
|
||||||
@@ -51,15 +48,18 @@ logger:
|
|||||||
nats:
|
nats:
|
||||||
authToken: "defaultFissionAuthToken"
|
authToken: "defaultFissionAuthToken"
|
||||||
clusterID: "fissionMQTrigger"
|
clusterID: "fissionMQTrigger"
|
||||||
|
|
||||||
|
|
||||||
## Persist data to a persistent volume.
|
## Persist data to a persistent volume.
|
||||||
persistence:
|
persistence:
|
||||||
enabled: true
|
enabled: true
|
||||||
## If defined, volume.beta.kubernetes.io/storage-class: <storageClass>
|
## If defined, storageClassName: <storageClass>
|
||||||
## Default: volume.alpha.kubernetes.io/storage-class: default
|
## If set to "-", storageClassName: "", which disables dynamic provisioning
|
||||||
|
## If undefined (the default) or set to null, no storageClassName spec is
|
||||||
|
## set, choosing the default provisioner. (gp2 on AWS, standard on
|
||||||
|
## GKE, AWS & OpenStack)
|
||||||
##
|
##
|
||||||
# storageClass:
|
# storageClass: "-"
|
||||||
accessMode: ReadWriteOnce
|
accessMode: ReadWriteOnce
|
||||||
size: 8Gi
|
size: 8Gi
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
name: fission-core
|
name: fission-core
|
||||||
version: 0.3.0
|
version: 0.4.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.3.0
|
appVersion: 0.4.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.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.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.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.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.3.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.4.1/fission-cli-windows.exe
|
||||||
|
|
||||||
2. Set the FISSION_URL and FISSION_ROUTER environment variables.
|
2. Set the FISSION_URL and FISSION_ROUTER environment variables.
|
||||||
|
|
||||||
|
|||||||
@@ -1,77 +1,3 @@
|
|||||||
{{ if .Values.openshift }}
|
|
||||||
|
|
||||||
# For openshift
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ProjectRequest
|
|
||||||
metadata:
|
|
||||||
name: fission
|
|
||||||
labels:
|
|
||||||
name: fission
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ProjectRequest
|
|
||||||
metadata:
|
|
||||||
name: {{ .Values.functionNamespace }}
|
|
||||||
labels:
|
|
||||||
name: fission-function
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: fission-admin
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ClusterRole
|
|
||||||
metadata:
|
|
||||||
name: fission:fission-admin
|
|
||||||
rules:
|
|
||||||
- apiGroups:
|
|
||||||
- extensions
|
|
||||||
attributeRestrictions: null
|
|
||||||
resources:
|
|
||||||
- deployments
|
|
||||||
verbs:
|
|
||||||
- create
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- update
|
|
||||||
- watch
|
|
||||||
- apiGroups:
|
|
||||||
- ""
|
|
||||||
attributeRestrictions: null
|
|
||||||
resources:
|
|
||||||
- pods
|
|
||||||
verbs:
|
|
||||||
- get
|
|
||||||
- list
|
|
||||||
- update
|
|
||||||
|
|
||||||
---
|
|
||||||
apiVersion: v1
|
|
||||||
groupNames: null
|
|
||||||
kind: RoleBinding
|
|
||||||
metadata:
|
|
||||||
name: fission:fission-admin
|
|
||||||
namespace: {{ .Values.functionNamespace }}
|
|
||||||
roleRef:
|
|
||||||
name: fission:fission-admin
|
|
||||||
subjects:
|
|
||||||
- kind: ServiceAccount
|
|
||||||
name: fission-admin
|
|
||||||
namespace: {{ .Release.Namespace }}
|
|
||||||
userNames:
|
|
||||||
- system:serviceaccount:fission:fission-admin
|
|
||||||
|
|
||||||
{{ else }}
|
|
||||||
|
|
||||||
# For all environments except openshift
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
@@ -131,7 +57,7 @@ roleRef:
|
|||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
metadata:
|
metadata:
|
||||||
name: fission-tpr
|
name: fission-crd
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: fission-svc
|
name: fission-svc
|
||||||
@@ -152,7 +78,7 @@ metadata:
|
|||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
metadata:
|
metadata:
|
||||||
name: fission-fetcher-tpr
|
name: fission-fetcher-crd
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: fission-fetcher
|
name: fission-fetcher
|
||||||
@@ -173,7 +99,7 @@ metadata:
|
|||||||
kind: ClusterRoleBinding
|
kind: ClusterRoleBinding
|
||||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||||
metadata:
|
metadata:
|
||||||
name: fission-builder-tpr
|
name: fission-builder-crd
|
||||||
subjects:
|
subjects:
|
||||||
- kind: ServiceAccount
|
- kind: ServiceAccount
|
||||||
name: fission-builder
|
name: fission-builder
|
||||||
@@ -183,8 +109,6 @@ roleRef:
|
|||||||
name: cluster-admin
|
name: cluster-admin
|
||||||
apiGroup: rbac.authorization.k8s.io
|
apiGroup: rbac.authorization.k8s.io
|
||||||
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: extensions/v1beta1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
@@ -226,16 +150,16 @@ spec:
|
|||||||
image: "{{ .Values.image }}:{{ .Values.imageTag }}"
|
image: "{{ .Values.image }}:{{ .Values.imageTag }}"
|
||||||
imagePullPolicy: {{ .Values.pullPolicy }}
|
imagePullPolicy: {{ .Values.pullPolicy }}
|
||||||
command: ["/fission-bundle"]
|
command: ["/fission-bundle"]
|
||||||
args: ["--routerPort", "8888", "--poolmgrUrl", "http://poolmgr.{{ .Release.Namespace }}"]
|
args: ["--routerPort", "8888", "--executorUrl", "http://executor.{{ .Release.Namespace }}"]
|
||||||
serviceAccount: fission-svc
|
serviceAccount: fission-svc
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: poolmgr
|
name: executor
|
||||||
labels:
|
labels:
|
||||||
svc: poolmgr
|
svc: executor
|
||||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||||
spec:
|
spec:
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
@@ -243,13 +167,13 @@ spec:
|
|||||||
- port: 80
|
- port: 80
|
||||||
targetPort: 8888
|
targetPort: 8888
|
||||||
selector:
|
selector:
|
||||||
svc: poolmgr
|
svc: executor
|
||||||
|
|
||||||
---
|
---
|
||||||
apiVersion: extensions/v1beta1
|
apiVersion: extensions/v1beta1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: poolmgr
|
name: executor
|
||||||
labels:
|
labels:
|
||||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||||
spec:
|
spec:
|
||||||
@@ -257,14 +181,14 @@ spec:
|
|||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
svc: poolmgr
|
svc: executor
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: poolmgr
|
- name: executor
|
||||||
image: "{{ .Values.image }}:{{ .Values.imageTag }}"
|
image: "{{ .Values.image }}:{{ .Values.imageTag }}"
|
||||||
imagePullPolicy: {{ .Values.pullPolicy }}
|
imagePullPolicy: {{ .Values.pullPolicy }}
|
||||||
command: ["/fission-bundle"]
|
command: ["/fission-bundle"]
|
||||||
args: ["--poolmgrPort", "8888", "--namespace", "{{ .Values.functionNamespace }}", "--fission-namespace", "{{ .Release.Namespace }}"]
|
args: ["--executorPort", "8888", "--namespace", "{{ .Values.functionNamespace }}", "--fission-namespace", "{{ .Release.Namespace }}"]
|
||||||
env:
|
env:
|
||||||
- name: FETCHER_IMAGE
|
- name: FETCHER_IMAGE
|
||||||
value: "{{ .Values.fetcherImage }}:{{ .Values.fetcherImageTag }}"
|
value: "{{ .Values.fetcherImage }}:{{ .Values.fetcherImageTag }}"
|
||||||
|
|||||||
@@ -7,17 +7,17 @@ metadata:
|
|||||||
app: fission-storage
|
app: fission-storage
|
||||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||||
release: "{{ .Release.Name }}"
|
release: "{{ .Release.Name }}"
|
||||||
annotations:
|
|
||||||
{{- if .Values.persistence.storageClass }}
|
|
||||||
volume.beta.kubernetes.io/storage-class: {{ .Values.persistence.storageClass | quote }}
|
|
||||||
{{- else }}
|
|
||||||
volume.alpha.kubernetes.io/storage-class: default
|
|
||||||
{{- end }}
|
|
||||||
spec:
|
spec:
|
||||||
accessModes:
|
accessModes:
|
||||||
- {{ .Values.persistence.accessMode | quote }}
|
- {{ .Values.persistence.accessMode | quote }}
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .Values.persistence.size | quote }}
|
storage: {{ .Values.persistence.size | quote }}
|
||||||
|
{{- if .Values.persistence.storageClass }}
|
||||||
|
{{- if (eq "-" .Values.persistence.storageClass) }}
|
||||||
|
storageClassName: ""
|
||||||
|
{{- else }}
|
||||||
|
storageClassName: {{ .Values.persistence.storageClass | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
# Fission chart configuration
|
# Fission chart configuration
|
||||||
#
|
#
|
||||||
|
|
||||||
## Kubernetes configuration
|
## Kubernetes configuration
|
||||||
## For minikube, set this to NodePort, elsewhere use LoadBalancer.
|
## For minikube, set this to NodePort, elsewhere use LoadBalancer.
|
||||||
@@ -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.1
|
||||||
|
|
||||||
## 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.1
|
||||||
|
|
||||||
## Port at which Fission controller service should be exposed
|
## Port at which Fission controller service should be exposed
|
||||||
controllerPort: 31313
|
controllerPort: 31313
|
||||||
@@ -35,16 +35,16 @@ functionNamespace: fission-function
|
|||||||
## the release namespace)
|
## the release namespace)
|
||||||
builderNamespace: fission-builder
|
builderNamespace: fission-builder
|
||||||
|
|
||||||
## Set up openshift RBAC rule
|
|
||||||
openshift: false
|
|
||||||
|
|
||||||
## Persist data to a persistent volume.
|
## Persist data to a persistent volume.
|
||||||
persistence:
|
persistence:
|
||||||
enabled: true
|
enabled: true
|
||||||
## If defined, volume.beta.kubernetes.io/storage-class: <storageClass>
|
## If defined, storageClassName: <storageClass>
|
||||||
## Default: volume.alpha.kubernetes.io/storage-class: default
|
## If set to "-", storageClassName: "", which disables dynamic provisioning
|
||||||
|
## If undefined (the default) or set to null, no storageClassName spec is
|
||||||
|
## set, choosing the default provisioner. (gp2 on AWS, standard on
|
||||||
|
## GKE, AWS & OpenStack)
|
||||||
##
|
##
|
||||||
# storageClass:
|
# storageClass: "-"
|
||||||
accessMode: ReadWriteOnce
|
accessMode: ReadWriteOnce
|
||||||
size: 8Gi
|
size: 8Gi
|
||||||
|
|
||||||
|
|||||||
+10
-6
@@ -26,16 +26,18 @@ import (
|
|||||||
"github.com/gorilla/handlers"
|
"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/client-go/1.5/pkg/api/errors"
|
kerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
|
"github.com/fission/fission/crd"
|
||||||
"github.com/fission/fission/fission/logdb"
|
"github.com/fission/fission/fission/logdb"
|
||||||
"github.com/fission/fission/tpr"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
API struct {
|
API struct {
|
||||||
fissionClient *tpr.FissionClient
|
fissionClient *crd.FissionClient
|
||||||
|
kubernetesClient *kubernetes.Clientset
|
||||||
storageServiceUrl string
|
storageServiceUrl string
|
||||||
builderManagerUrl string
|
builderManagerUrl string
|
||||||
workflowApiUrl string
|
workflowApiUrl string
|
||||||
@@ -49,7 +51,7 @@ type (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func MakeAPI() (*API, error) {
|
func MakeAPI() (*API, error) {
|
||||||
api, err := makeTPRBackedAPI()
|
api, err := makeCRDBackedAPI()
|
||||||
|
|
||||||
u := os.Getenv("STORAGE_SERVICE_URL")
|
u := os.Getenv("STORAGE_SERVICE_URL")
|
||||||
if len(u) > 0 {
|
if len(u) > 0 {
|
||||||
@@ -118,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.3.0\"}\n")
|
fmt.Fprintf(w, "{\"message\": \"Fission API\", \"version\": \"0.4.1\"}\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) ApiVersionMismatchHandler(w http.ResponseWriter, r *http.Request) {
|
func (api *API) ApiVersionMismatchHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -174,10 +176,12 @@ func (api *API) Serve(port int) {
|
|||||||
r.HandleFunc("/v2/triggers/messagequeue/{mqTrigger}", api.MessageQueueTriggerApiUpdate).Methods("PUT")
|
r.HandleFunc("/v2/triggers/messagequeue/{mqTrigger}", api.MessageQueueTriggerApiUpdate).Methods("PUT")
|
||||||
r.HandleFunc("/v2/triggers/messagequeue/{mqTrigger}", api.MessageQueueTriggerApiDelete).Methods("DELETE")
|
r.HandleFunc("/v2/triggers/messagequeue/{mqTrigger}", api.MessageQueueTriggerApiDelete).Methods("DELETE")
|
||||||
|
|
||||||
|
r.HandleFunc("/v2/deleteTpr", api.Tpr2crdApi).Methods("DELETE")
|
||||||
|
|
||||||
r.HandleFunc("/proxy/{dbType}", api.FunctionLogsApiPost).Methods("POST")
|
r.HandleFunc("/proxy/{dbType}", api.FunctionLogsApiPost).Methods("POST")
|
||||||
r.HandleFunc("/proxy/storage/v1/archive", api.StorageServiceProxy)
|
r.HandleFunc("/proxy/storage/v1/archive", api.StorageServiceProxy)
|
||||||
r.HandleFunc("/proxy/buildermgr/v1/build", api.BuilderManagerBuildProxy)
|
r.HandleFunc("/proxy/buildermgr/v1/build", api.BuilderManagerBuildProxy)
|
||||||
r.HandleFunc("/proxy/buildermgr/v1/builder", api.BuilderManagerEnvBuilderProxy)
|
r.HandleFunc("/proxy/logs/{function}", api.FunctionPodLogs).Methods("POST")
|
||||||
r.HandleFunc("/proxy/workflows-apiserver/{path:.*}", api.WorkflowApiserverProxy)
|
r.HandleFunc("/proxy/workflows-apiserver/{path:.*}", api.WorkflowApiserverProxy)
|
||||||
|
|
||||||
address := fmt.Sprintf(":%v", port)
|
address := fmt.Sprintf(":%v", port)
|
||||||
|
|||||||
+50
-45
@@ -18,6 +18,7 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -25,11 +26,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
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/controller/client"
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
var g struct {
|
var g struct {
|
||||||
@@ -72,13 +73,10 @@ func assertCronSpecFails(err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFunctionApi(t *testing.T) {
|
func TestFunctionApi(t *testing.T) {
|
||||||
name1 := "foo"
|
testFunc := &crd.Function{
|
||||||
name2 := "bar"
|
Metadata: metav1.ObjectMeta{
|
||||||
|
Name: "foo",
|
||||||
testFunc := &tpr.Function{
|
Namespace: metav1.NamespaceDefault,
|
||||||
Metadata: api.ObjectMeta{
|
|
||||||
Name: name1,
|
|
||||||
Namespace: api.NamespaceDefault,
|
|
||||||
},
|
},
|
||||||
Spec: fission.FunctionSpec{
|
Spec: fission.FunctionSpec{
|
||||||
Environment: fission.EnvironmentReference{
|
Environment: fission.EnvironmentReference{
|
||||||
@@ -89,30 +87,36 @@ func TestFunctionApi(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := g.client.FunctionGet(&api.ObjectMeta{
|
_, err := g.client.FunctionGet(&metav1.ObjectMeta{
|
||||||
Name: testFunc.Metadata.Name,
|
Name: testFunc.Metadata.Name,
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
})
|
})
|
||||||
assertNotFoundFailure(err, "function")
|
assertNotFoundFailure(err, "function")
|
||||||
|
|
||||||
_, err = g.client.FunctionCreate(testFunc)
|
m, err := g.client.FunctionCreate(testFunc)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
defer func() {
|
||||||
|
err := g.client.FunctionDelete(m)
|
||||||
|
panicIf(err)
|
||||||
|
}()
|
||||||
|
|
||||||
_, err = g.client.FunctionCreate(testFunc)
|
_, err = g.client.FunctionCreate(testFunc)
|
||||||
assertNameReuseFailure(err, "function")
|
assertNameReuseFailure(err, "function")
|
||||||
|
|
||||||
|
testFunc.Metadata.ResourceVersion = m.ResourceVersion
|
||||||
testFunc.Spec.Package.FunctionName = "yyy"
|
testFunc.Spec.Package.FunctionName = "yyy"
|
||||||
_, err = g.client.FunctionUpdate(testFunc)
|
_, err = g.client.FunctionUpdate(testFunc)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
testFunc.Metadata.Name = name2
|
testFunc.Metadata.ResourceVersion = ""
|
||||||
_, err = g.client.FunctionCreate(testFunc)
|
testFunc.Metadata.Name = "bar"
|
||||||
|
m2, err := g.client.FunctionCreate(testFunc)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
defer g.client.FunctionDelete(m2)
|
||||||
|
|
||||||
funcs, err := g.client.FunctionList()
|
funcs, err := g.client.FunctionList()
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
assert(len(funcs) == 2,
|
assert(len(funcs) == 2, fmt.Sprintf("created two functions, but found %v", len(funcs)))
|
||||||
"created two functions, but didn't find them")
|
|
||||||
|
|
||||||
funcs_url := g.client.Url + "/v2/functions"
|
funcs_url := g.client.Url + "/v2/functions"
|
||||||
resp, err := http.Get(funcs_url)
|
resp, err := http.Get(funcs_url)
|
||||||
@@ -127,18 +131,13 @@ func TestFunctionApi(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(found, "incorrect response content type")
|
assert(found, "incorrect response content type")
|
||||||
|
|
||||||
err = g.client.FunctionDelete(&api.ObjectMeta{Name: name1, Namespace: api.NamespaceDefault})
|
|
||||||
panicIf(err)
|
|
||||||
err = g.client.FunctionDelete(&api.ObjectMeta{Name: name2, Namespace: api.NamespaceDefault})
|
|
||||||
panicIf(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHTTPTriggerApi(t *testing.T) {
|
func TestHTTPTriggerApi(t *testing.T) {
|
||||||
testTrigger := &tpr.Httptrigger{
|
testTrigger := &crd.HTTPTrigger{
|
||||||
Metadata: api.ObjectMeta{
|
Metadata: metav1.ObjectMeta{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
},
|
},
|
||||||
Spec: fission.HTTPTriggerSpec{
|
Spec: fission.HTTPTriggerSpec{
|
||||||
RelativeURL: "/hello",
|
RelativeURL: "/hello",
|
||||||
@@ -148,9 +147,9 @@ func TestHTTPTriggerApi(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := g.client.HTTPTriggerGet(&api.ObjectMeta{
|
_, err := g.client.HTTPTriggerGet(&metav1.ObjectMeta{
|
||||||
Name: testTrigger.Metadata.Name,
|
Name: testTrigger.Metadata.Name,
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
})
|
})
|
||||||
assertNotFoundFailure(err, "httptrigger")
|
assertNotFoundFailure(err, "httptrigger")
|
||||||
|
|
||||||
@@ -165,10 +164,12 @@ func TestHTTPTriggerApi(t *testing.T) {
|
|||||||
panicIf(err)
|
panicIf(err)
|
||||||
assert(testTrigger.Spec == tr.Spec, "trigger should match after reading")
|
assert(testTrigger.Spec == tr.Spec, "trigger should match after reading")
|
||||||
|
|
||||||
|
testTrigger.Metadata.ResourceVersion = m.ResourceVersion
|
||||||
testTrigger.Spec.RelativeURL = "/hi"
|
testTrigger.Spec.RelativeURL = "/hi"
|
||||||
_, err = g.client.HTTPTriggerUpdate(testTrigger)
|
_, err = g.client.HTTPTriggerUpdate(testTrigger)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
|
testTrigger.Metadata.ResourceVersion = ""
|
||||||
testTrigger.Metadata.Name = "yyy"
|
testTrigger.Metadata.Name = "yyy"
|
||||||
_, err = g.client.HTTPTriggerCreate(testTrigger)
|
_, err = g.client.HTTPTriggerCreate(testTrigger)
|
||||||
assert(err != nil, "duplicate trigger should not be allowed")
|
assert(err != nil, "duplicate trigger should not be allowed")
|
||||||
@@ -180,14 +181,14 @@ func TestHTTPTriggerApi(t *testing.T) {
|
|||||||
|
|
||||||
ts, err := g.client.HTTPTriggerList()
|
ts, err := g.client.HTTPTriggerList()
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
assert(len(ts) == 2, "created two triggers, but didn't find them")
|
assert(len(ts) == 2, fmt.Sprintf("created two triggers, but found %v", len(ts)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEnvironmentApi(t *testing.T) {
|
func TestEnvironmentApi(t *testing.T) {
|
||||||
testEnv := &tpr.Environment{
|
testEnv := &crd.Environment{
|
||||||
Metadata: api.ObjectMeta{
|
Metadata: metav1.ObjectMeta{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
},
|
},
|
||||||
Spec: fission.EnvironmentSpec{
|
Spec: fission.EnvironmentSpec{
|
||||||
Runtime: fission.Runtime{
|
Runtime: fission.Runtime{
|
||||||
@@ -195,9 +196,9 @@ func TestEnvironmentApi(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := g.client.EnvironmentGet(&api.ObjectMeta{
|
_, err := g.client.EnvironmentGet(&metav1.ObjectMeta{
|
||||||
Name: testEnv.Metadata.Name,
|
Name: testEnv.Metadata.Name,
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
})
|
})
|
||||||
assertNotFoundFailure(err, "environment")
|
assertNotFoundFailure(err, "environment")
|
||||||
|
|
||||||
@@ -212,10 +213,12 @@ func TestEnvironmentApi(t *testing.T) {
|
|||||||
panicIf(err)
|
panicIf(err)
|
||||||
assert(testEnv.Spec == e.Spec, "env should match after reading")
|
assert(testEnv.Spec == e.Spec, "env should match after reading")
|
||||||
|
|
||||||
|
testEnv.Metadata.ResourceVersion = m.ResourceVersion
|
||||||
testEnv.Spec.Runtime.Image = "another-img"
|
testEnv.Spec.Runtime.Image = "another-img"
|
||||||
_, err = g.client.EnvironmentUpdate(testEnv)
|
_, err = g.client.EnvironmentUpdate(testEnv)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
|
testEnv.Metadata.ResourceVersion = ""
|
||||||
testEnv.Metadata.Name = "bar"
|
testEnv.Metadata.Name = "bar"
|
||||||
m2, err := g.client.EnvironmentCreate(testEnv)
|
m2, err := g.client.EnvironmentCreate(testEnv)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
@@ -223,14 +226,14 @@ func TestEnvironmentApi(t *testing.T) {
|
|||||||
|
|
||||||
ts, err := g.client.EnvironmentList()
|
ts, err := g.client.EnvironmentList()
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
assert(len(ts) == 2, "created two envs, but didn't find them")
|
assert(len(ts) == 2, fmt.Sprintf("created two envs, but found %v", len(ts)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWatchApi(t *testing.T) {
|
func TestWatchApi(t *testing.T) {
|
||||||
testWatch := &tpr.Kuberneteswatchtrigger{
|
testWatch := &crd.KubernetesWatchTrigger{
|
||||||
Metadata: api.ObjectMeta{
|
Metadata: metav1.ObjectMeta{
|
||||||
Name: "xxx",
|
Name: "xxx",
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
},
|
},
|
||||||
Spec: fission.KubernetesWatchTriggerSpec{
|
Spec: fission.KubernetesWatchTriggerSpec{
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
@@ -241,9 +244,9 @@ func TestWatchApi(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := g.client.WatchGet(&api.ObjectMeta{
|
_, err := g.client.WatchGet(&metav1.ObjectMeta{
|
||||||
Name: testWatch.Metadata.Name,
|
Name: testWatch.Metadata.Name,
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
})
|
})
|
||||||
assertNotFoundFailure(err, "watch")
|
assertNotFoundFailure(err, "watch")
|
||||||
|
|
||||||
@@ -267,14 +270,14 @@ func TestWatchApi(t *testing.T) {
|
|||||||
|
|
||||||
ws, err := g.client.WatchList()
|
ws, err := g.client.WatchList()
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
assert(len(ws) == 2, "created two envs, but didn't find them")
|
assert(len(ws) == 2, fmt.Sprintf("created two watches, but found %v", len(ws)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTimeTriggerApi(t *testing.T) {
|
func TestTimeTriggerApi(t *testing.T) {
|
||||||
testTrigger := &tpr.Timetrigger{
|
testTrigger := &crd.TimeTrigger{
|
||||||
Metadata: api.ObjectMeta{
|
Metadata: metav1.ObjectMeta{
|
||||||
Name: "xxx",
|
Name: "xxx",
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
},
|
},
|
||||||
Spec: fission.TimeTriggerSpec{
|
Spec: fission.TimeTriggerSpec{
|
||||||
Cron: "0 30 * * * *",
|
Cron: "0 30 * * * *",
|
||||||
@@ -284,7 +287,7 @@ func TestTimeTriggerApi(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := g.client.TimeTriggerGet(&api.ObjectMeta{Name: testTrigger.Metadata.Name})
|
_, err := g.client.TimeTriggerGet(&metav1.ObjectMeta{Name: testTrigger.Metadata.Name})
|
||||||
assertNotFoundFailure(err, "trigger")
|
assertNotFoundFailure(err, "trigger")
|
||||||
|
|
||||||
m, err := g.client.TimeTriggerCreate(testTrigger)
|
m, err := g.client.TimeTriggerCreate(testTrigger)
|
||||||
@@ -298,10 +301,12 @@ func TestTimeTriggerApi(t *testing.T) {
|
|||||||
panicIf(err)
|
panicIf(err)
|
||||||
assert(testTrigger.Spec == tr.Spec, "trigger should match after reading")
|
assert(testTrigger.Spec == tr.Spec, "trigger should match after reading")
|
||||||
|
|
||||||
|
testTrigger.Metadata.ResourceVersion = m.ResourceVersion
|
||||||
testTrigger.Spec.Cron = "@hourly"
|
testTrigger.Spec.Cron = "@hourly"
|
||||||
_, err = g.client.TimeTriggerUpdate(testTrigger)
|
_, err = g.client.TimeTriggerUpdate(testTrigger)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
|
testTrigger.Metadata.ResourceVersion = ""
|
||||||
testTrigger.Metadata.Name = "yyy"
|
testTrigger.Metadata.Name = "yyy"
|
||||||
testTrigger.Spec.Cron = "Not valid cron spec"
|
testTrigger.Spec.Cron = "Not valid cron spec"
|
||||||
_, err = g.client.TimeTriggerCreate(testTrigger)
|
_, err = g.client.TimeTriggerCreate(testTrigger)
|
||||||
@@ -309,7 +314,7 @@ func TestTimeTriggerApi(t *testing.T) {
|
|||||||
|
|
||||||
ts, err := g.client.TimeTriggerList()
|
ts, err := g.client.TimeTriggerList()
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
assert(len(ts) == 1, "created one trigger, but didn't find it")
|
assert(len(ts) == 1, fmt.Sprintf("created two time triggers, but found %v", len(ts)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
@@ -324,7 +329,7 @@ func TestMain(m *testing.M) {
|
|||||||
|
|
||||||
go Start(8888)
|
go Start(8888)
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
g.client = client.MakeClient("http://localhost:8888")
|
g.client = client.MakeClient("http://localhost:8888")
|
||||||
|
|
||||||
resp, err := http.Get("http://localhost:8888/")
|
resp, err := http.Get("http://localhost:8888/")
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import (
|
|||||||
|
|
||||||
func (api *API) BuilderManagerBuildProxy(w http.ResponseWriter, r *http.Request) {
|
func (api *API) BuilderManagerBuildProxy(w http.ResponseWriter, r *http.Request) {
|
||||||
u := api.builderManagerUrl + "/v1/build"
|
u := api.builderManagerUrl + "/v1/build"
|
||||||
proxy, err := api._getBuilderManagerProxy(u)
|
proxy, err := api.getBuilderManagerProxy(u)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := fmt.Sprintf("Failed to establish proxy server: %v", err)
|
msg := fmt.Sprintf("Failed to establish proxy server: %v", err)
|
||||||
log.Println(msg)
|
log.Println(msg)
|
||||||
@@ -36,19 +36,7 @@ func (api *API) BuilderManagerBuildProxy(w http.ResponseWriter, r *http.Request)
|
|||||||
proxy.ServeHTTP(w, r)
|
proxy.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *API) BuilderManagerEnvBuilderProxy(w http.ResponseWriter, r *http.Request) {
|
func (api *API) getBuilderManagerProxy(targetUrl string) (*httputil.ReverseProxy, error) {
|
||||||
u := api.builderManagerUrl + "/v1/builder"
|
|
||||||
proxy, err := api._getBuilderManagerProxy(u)
|
|
||||||
if err != nil {
|
|
||||||
msg := fmt.Sprintf("Failed to establish proxy server: %v", err)
|
|
||||||
log.Println(msg)
|
|
||||||
http.Error(w, msg, 500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
proxy.ServeHTTP(w, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (api *API) _getBuilderManagerProxy(targetUrl string) (*httputil.ReverseProxy, error) {
|
|
||||||
svcUrl, err := url.Parse(targetUrl)
|
svcUrl, err := url.Parse(targetUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Client) EnvironmentCreate(env *tpr.Environment) (*api.ObjectMeta, error) {
|
func (c *Client) EnvironmentCreate(env *crd.Environment) (*metav1.ObjectMeta, error) {
|
||||||
reqbody, err := json.Marshal(env)
|
reqbody, err := json.Marshal(env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -44,7 +44,7 @@ func (c *Client) EnvironmentCreate(env *tpr.Environment) (*api.ObjectMeta, error
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var m api.ObjectMeta
|
var m metav1.ObjectMeta
|
||||||
err = json.Unmarshal(body, &m)
|
err = json.Unmarshal(body, &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -53,7 +53,7 @@ func (c *Client) EnvironmentCreate(env *tpr.Environment) (*api.ObjectMeta, error
|
|||||||
return &m, nil
|
return &m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) EnvironmentGet(m *api.ObjectMeta) (*tpr.Environment, error) {
|
func (c *Client) EnvironmentGet(m *metav1.ObjectMeta) (*crd.Environment, error) {
|
||||||
relativeUrl := fmt.Sprintf("environments/%v", m.Name)
|
relativeUrl := fmt.Sprintf("environments/%v", m.Name)
|
||||||
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ func (c *Client) EnvironmentGet(m *api.ObjectMeta) (*tpr.Environment, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var env tpr.Environment
|
var env crd.Environment
|
||||||
err = json.Unmarshal(body, &env)
|
err = json.Unmarshal(body, &env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -77,7 +77,7 @@ func (c *Client) EnvironmentGet(m *api.ObjectMeta) (*tpr.Environment, error) {
|
|||||||
return &env, nil
|
return &env, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) EnvironmentUpdate(env *tpr.Environment) (*api.ObjectMeta, error) {
|
func (c *Client) EnvironmentUpdate(env *crd.Environment) (*metav1.ObjectMeta, error) {
|
||||||
reqbody, err := json.Marshal(env)
|
reqbody, err := json.Marshal(env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -95,7 +95,7 @@ func (c *Client) EnvironmentUpdate(env *tpr.Environment) (*api.ObjectMeta, error
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var m api.ObjectMeta
|
var m metav1.ObjectMeta
|
||||||
err = json.Unmarshal(body, &m)
|
err = json.Unmarshal(body, &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -103,14 +103,14 @@ func (c *Client) EnvironmentUpdate(env *tpr.Environment) (*api.ObjectMeta, error
|
|||||||
return &m, nil
|
return &m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) EnvironmentDelete(m *api.ObjectMeta) error {
|
func (c *Client) EnvironmentDelete(m *metav1.ObjectMeta) error {
|
||||||
relativeUrl := fmt.Sprintf("environments/%v", m.Name)
|
relativeUrl := fmt.Sprintf("environments/%v", m.Name)
|
||||||
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
||||||
|
|
||||||
return c.delete(relativeUrl)
|
return c.delete(relativeUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) EnvironmentList() ([]tpr.Environment, error) {
|
func (c *Client) EnvironmentList() ([]crd.Environment, error) {
|
||||||
resp, err := http.Get(c.url("environments"))
|
resp, err := http.Get(c.url("environments"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -122,7 +122,7 @@ func (c *Client) EnvironmentList() ([]tpr.Environment, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
envs := make([]tpr.Environment, 0)
|
envs := make([]crd.Environment, 0)
|
||||||
err = json.Unmarshal(body, &envs)
|
err = json.Unmarshal(body, &envs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Client) FunctionCreate(f *tpr.Function) (*api.ObjectMeta, error) {
|
func (c *Client) FunctionCreate(f *crd.Function) (*metav1.ObjectMeta, error) {
|
||||||
|
|
||||||
reqbody, err := json.Marshal(f)
|
reqbody, err := json.Marshal(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -45,7 +45,7 @@ func (c *Client) FunctionCreate(f *tpr.Function) (*api.ObjectMeta, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var m api.ObjectMeta
|
var m metav1.ObjectMeta
|
||||||
err = json.Unmarshal(body, &m)
|
err = json.Unmarshal(body, &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -54,7 +54,7 @@ func (c *Client) FunctionCreate(f *tpr.Function) (*api.ObjectMeta, error) {
|
|||||||
return &m, nil
|
return &m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) FunctionGet(m *api.ObjectMeta) (*tpr.Function, error) {
|
func (c *Client) FunctionGet(m *metav1.ObjectMeta) (*crd.Function, error) {
|
||||||
relativeUrl := fmt.Sprintf("functions/%v", m.Name)
|
relativeUrl := fmt.Sprintf("functions/%v", m.Name)
|
||||||
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ func (c *Client) FunctionGet(m *api.ObjectMeta) (*tpr.Function, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var f tpr.Function
|
var f crd.Function
|
||||||
err = json.Unmarshal(body, &f)
|
err = json.Unmarshal(body, &f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -78,7 +78,7 @@ func (c *Client) FunctionGet(m *api.ObjectMeta) (*tpr.Function, error) {
|
|||||||
return &f, nil
|
return &f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) FunctionGetRawDeployment(m *api.ObjectMeta) ([]byte, error) {
|
func (c *Client) FunctionGetRawDeployment(m *metav1.ObjectMeta) ([]byte, error) {
|
||||||
relativeUrl := fmt.Sprintf("functions/%v", m.Name)
|
relativeUrl := fmt.Sprintf("functions/%v", m.Name)
|
||||||
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
||||||
relativeUrl += fmt.Sprintf("&deploymentraw=1")
|
relativeUrl += fmt.Sprintf("&deploymentraw=1")
|
||||||
@@ -92,7 +92,7 @@ func (c *Client) FunctionGetRawDeployment(m *api.ObjectMeta) ([]byte, error) {
|
|||||||
return c.handleResponse(resp)
|
return c.handleResponse(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) FunctionUpdate(f *tpr.Function) (*api.ObjectMeta, error) {
|
func (c *Client) FunctionUpdate(f *crd.Function) (*metav1.ObjectMeta, error) {
|
||||||
reqbody, err := json.Marshal(f)
|
reqbody, err := json.Marshal(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -110,7 +110,7 @@ func (c *Client) FunctionUpdate(f *tpr.Function) (*api.ObjectMeta, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var m api.ObjectMeta
|
var m metav1.ObjectMeta
|
||||||
err = json.Unmarshal(body, &m)
|
err = json.Unmarshal(body, &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -118,13 +118,13 @@ func (c *Client) FunctionUpdate(f *tpr.Function) (*api.ObjectMeta, error) {
|
|||||||
return &m, nil
|
return &m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) FunctionDelete(m *api.ObjectMeta) error {
|
func (c *Client) FunctionDelete(m *metav1.ObjectMeta) error {
|
||||||
relativeUrl := fmt.Sprintf("functions/%v", m.Name)
|
relativeUrl := fmt.Sprintf("functions/%v", m.Name)
|
||||||
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
||||||
return c.delete(relativeUrl)
|
return c.delete(relativeUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) FunctionList() ([]tpr.Function, error) {
|
func (c *Client) FunctionList() ([]crd.Function, error) {
|
||||||
resp, err := http.Get(c.url("functions"))
|
resp, err := http.Get(c.url("functions"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -136,7 +136,7 @@ func (c *Client) FunctionList() ([]tpr.Function, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
funcs := make([]tpr.Function, 0)
|
funcs := make([]crd.Function, 0)
|
||||||
err = json.Unmarshal(body, &funcs)
|
err = json.Unmarshal(body, &funcs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Client) HTTPTriggerCreate(t *tpr.Httptrigger) (*api.ObjectMeta, error) {
|
func (c *Client) HTTPTriggerCreate(t *crd.HTTPTrigger) (*metav1.ObjectMeta, error) {
|
||||||
reqbody, err := json.Marshal(t)
|
reqbody, err := json.Marshal(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -44,7 +44,7 @@ func (c *Client) HTTPTriggerCreate(t *tpr.Httptrigger) (*api.ObjectMeta, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var m api.ObjectMeta
|
var m metav1.ObjectMeta
|
||||||
err = json.Unmarshal(body, &m)
|
err = json.Unmarshal(body, &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -53,7 +53,7 @@ func (c *Client) HTTPTriggerCreate(t *tpr.Httptrigger) (*api.ObjectMeta, error)
|
|||||||
return &m, nil
|
return &m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) HTTPTriggerGet(m *api.ObjectMeta) (*tpr.Httptrigger, error) {
|
func (c *Client) HTTPTriggerGet(m *metav1.ObjectMeta) (*crd.HTTPTrigger, error) {
|
||||||
relativeUrl := fmt.Sprintf("triggers/http/%v", m.Name)
|
relativeUrl := fmt.Sprintf("triggers/http/%v", m.Name)
|
||||||
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ func (c *Client) HTTPTriggerGet(m *api.ObjectMeta) (*tpr.Httptrigger, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var t tpr.Httptrigger
|
var t crd.HTTPTrigger
|
||||||
err = json.Unmarshal(body, &t)
|
err = json.Unmarshal(body, &t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -77,7 +77,7 @@ func (c *Client) HTTPTriggerGet(m *api.ObjectMeta) (*tpr.Httptrigger, error) {
|
|||||||
return &t, nil
|
return &t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) HTTPTriggerUpdate(t *tpr.Httptrigger) (*api.ObjectMeta, error) {
|
func (c *Client) HTTPTriggerUpdate(t *crd.HTTPTrigger) (*metav1.ObjectMeta, error) {
|
||||||
reqbody, err := json.Marshal(t)
|
reqbody, err := json.Marshal(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -95,7 +95,7 @@ func (c *Client) HTTPTriggerUpdate(t *tpr.Httptrigger) (*api.ObjectMeta, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var m api.ObjectMeta
|
var m metav1.ObjectMeta
|
||||||
err = json.Unmarshal(body, &m)
|
err = json.Unmarshal(body, &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -103,13 +103,13 @@ func (c *Client) HTTPTriggerUpdate(t *tpr.Httptrigger) (*api.ObjectMeta, error)
|
|||||||
return &m, nil
|
return &m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) HTTPTriggerDelete(m *api.ObjectMeta) error {
|
func (c *Client) HTTPTriggerDelete(m *metav1.ObjectMeta) error {
|
||||||
relativeUrl := fmt.Sprintf("triggers/http/%v", m.Name)
|
relativeUrl := fmt.Sprintf("triggers/http/%v", m.Name)
|
||||||
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
||||||
return c.delete(relativeUrl)
|
return c.delete(relativeUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) HTTPTriggerList() ([]tpr.Httptrigger, error) {
|
func (c *Client) HTTPTriggerList() ([]crd.HTTPTrigger, error) {
|
||||||
resp, err := http.Get(c.url("triggers/http"))
|
resp, err := http.Get(c.url("triggers/http"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -121,7 +121,7 @@ func (c *Client) HTTPTriggerList() ([]tpr.Httptrigger, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
triggers := make([]tpr.Httptrigger, 0)
|
triggers := make([]crd.HTTPTrigger, 0)
|
||||||
err = json.Unmarshal(body, &triggers)
|
err = json.Unmarshal(body, &triggers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -22,13 +22,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Client) WatchCreate(w *tpr.Kuberneteswatchtrigger) (*api.ObjectMeta, error) {
|
func (c *Client) WatchCreate(w *crd.KubernetesWatchTrigger) (*metav1.ObjectMeta, error) {
|
||||||
reqbody, err := json.Marshal(w)
|
reqbody, err := json.Marshal(w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -45,7 +45,7 @@ func (c *Client) WatchCreate(w *tpr.Kuberneteswatchtrigger) (*api.ObjectMeta, er
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var m api.ObjectMeta
|
var m metav1.ObjectMeta
|
||||||
err = json.Unmarshal(body, &m)
|
err = json.Unmarshal(body, &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -54,7 +54,7 @@ func (c *Client) WatchCreate(w *tpr.Kuberneteswatchtrigger) (*api.ObjectMeta, er
|
|||||||
return &m, nil
|
return &m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) WatchGet(m *api.ObjectMeta) (*tpr.Kuberneteswatchtrigger, error) {
|
func (c *Client) WatchGet(m *metav1.ObjectMeta) (*crd.KubernetesWatchTrigger, error) {
|
||||||
relativeUrl := fmt.Sprintf("watches/%v", m.Name)
|
relativeUrl := fmt.Sprintf("watches/%v", m.Name)
|
||||||
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ func (c *Client) WatchGet(m *api.ObjectMeta) (*tpr.Kuberneteswatchtrigger, error
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var w tpr.Kuberneteswatchtrigger
|
var w crd.KubernetesWatchTrigger
|
||||||
err = json.Unmarshal(body, &w)
|
err = json.Unmarshal(body, &w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -78,18 +78,18 @@ func (c *Client) WatchGet(m *api.ObjectMeta) (*tpr.Kuberneteswatchtrigger, error
|
|||||||
return &w, nil
|
return &w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) WatchUpdate(w *tpr.Kuberneteswatchtrigger) (*api.ObjectMeta, error) {
|
func (c *Client) WatchUpdate(w *crd.KubernetesWatchTrigger) (*metav1.ObjectMeta, error) {
|
||||||
return nil, fission.MakeError(fission.ErrorNotImplmented,
|
return nil, fission.MakeError(fission.ErrorNotImplmented,
|
||||||
"watch update not implemented")
|
"watch update not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) WatchDelete(m *api.ObjectMeta) error {
|
func (c *Client) WatchDelete(m *metav1.ObjectMeta) error {
|
||||||
relativeUrl := fmt.Sprintf("watches/%v", m.Name)
|
relativeUrl := fmt.Sprintf("watches/%v", m.Name)
|
||||||
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
||||||
return c.delete(relativeUrl)
|
return c.delete(relativeUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) WatchList() ([]tpr.Kuberneteswatchtrigger, error) {
|
func (c *Client) WatchList() ([]crd.KubernetesWatchTrigger, error) {
|
||||||
resp, err := http.Get(c.url("watches"))
|
resp, err := http.Get(c.url("watches"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -101,7 +101,7 @@ func (c *Client) WatchList() ([]tpr.Kuberneteswatchtrigger, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
watches := make([]tpr.Kuberneteswatchtrigger, 0)
|
watches := make([]crd.KubernetesWatchTrigger, 0)
|
||||||
err = json.Unmarshal(body, &watches)
|
err = json.Unmarshal(body, &watches)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Client) MessageQueueTriggerCreate(t *tpr.Messagequeuetrigger) (*api.ObjectMeta, error) {
|
func (c *Client) MessageQueueTriggerCreate(t *crd.MessageQueueTrigger) (*metav1.ObjectMeta, error) {
|
||||||
reqbody, err := json.Marshal(t)
|
reqbody, err := json.Marshal(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -44,7 +44,7 @@ func (c *Client) MessageQueueTriggerCreate(t *tpr.Messagequeuetrigger) (*api.Obj
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var m api.ObjectMeta
|
var m metav1.ObjectMeta
|
||||||
err = json.Unmarshal(body, &m)
|
err = json.Unmarshal(body, &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -53,7 +53,7 @@ func (c *Client) MessageQueueTriggerCreate(t *tpr.Messagequeuetrigger) (*api.Obj
|
|||||||
return &m, nil
|
return &m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) MessageQueueTriggerGet(m *api.ObjectMeta) (*tpr.Messagequeuetrigger, error) {
|
func (c *Client) MessageQueueTriggerGet(m *metav1.ObjectMeta) (*crd.MessageQueueTrigger, error) {
|
||||||
relativeUrl := fmt.Sprintf("triggers/messagequeue/%v", m.Name)
|
relativeUrl := fmt.Sprintf("triggers/messagequeue/%v", m.Name)
|
||||||
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ func (c *Client) MessageQueueTriggerGet(m *api.ObjectMeta) (*tpr.Messagequeuetri
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var t tpr.Messagequeuetrigger
|
var t crd.MessageQueueTrigger
|
||||||
err = json.Unmarshal(body, &t)
|
err = json.Unmarshal(body, &t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -77,7 +77,7 @@ func (c *Client) MessageQueueTriggerGet(m *api.ObjectMeta) (*tpr.Messagequeuetri
|
|||||||
return &t, nil
|
return &t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) MessageQueueTriggerUpdate(mqTrigger *tpr.Messagequeuetrigger) (*api.ObjectMeta, error) {
|
func (c *Client) MessageQueueTriggerUpdate(mqTrigger *crd.MessageQueueTrigger) (*metav1.ObjectMeta, error) {
|
||||||
reqbody, err := json.Marshal(mqTrigger)
|
reqbody, err := json.Marshal(mqTrigger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -95,7 +95,7 @@ func (c *Client) MessageQueueTriggerUpdate(mqTrigger *tpr.Messagequeuetrigger) (
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var m api.ObjectMeta
|
var m metav1.ObjectMeta
|
||||||
err = json.Unmarshal(body, &m)
|
err = json.Unmarshal(body, &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -103,13 +103,13 @@ func (c *Client) MessageQueueTriggerUpdate(mqTrigger *tpr.Messagequeuetrigger) (
|
|||||||
return &m, nil
|
return &m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) MessageQueueTriggerDelete(m *api.ObjectMeta) error {
|
func (c *Client) MessageQueueTriggerDelete(m *metav1.ObjectMeta) error {
|
||||||
relativeUrl := fmt.Sprintf("triggers/messagequeue/%v", m.Name)
|
relativeUrl := fmt.Sprintf("triggers/messagequeue/%v", m.Name)
|
||||||
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
||||||
return c.delete(relativeUrl)
|
return c.delete(relativeUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) MessageQueueTriggerList(mqType string) ([]tpr.Messagequeuetrigger, error) {
|
func (c *Client) MessageQueueTriggerList(mqType string) ([]crd.MessageQueueTrigger, error) {
|
||||||
relativeUrl := "triggers/messagequeue"
|
relativeUrl := "triggers/messagequeue"
|
||||||
if len(mqType) > 0 {
|
if len(mqType) > 0 {
|
||||||
// TODO remove this, replace with field selector
|
// TODO remove this, replace with field selector
|
||||||
@@ -127,7 +127,7 @@ func (c *Client) MessageQueueTriggerList(mqType string) ([]tpr.Messagequeuetrigg
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
triggers := make([]tpr.Messagequeuetrigger, 0)
|
triggers := make([]crd.MessageQueueTrigger, 0)
|
||||||
err = json.Unmarshal(body, &triggers)
|
err = json.Unmarshal(body, &triggers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Client) PackageCreate(f *tpr.Package) (*api.ObjectMeta, error) {
|
func (c *Client) PackageCreate(f *crd.Package) (*metav1.ObjectMeta, error) {
|
||||||
|
|
||||||
reqbody, err := json.Marshal(f)
|
reqbody, err := json.Marshal(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -45,7 +45,7 @@ func (c *Client) PackageCreate(f *tpr.Package) (*api.ObjectMeta, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var m api.ObjectMeta
|
var m metav1.ObjectMeta
|
||||||
err = json.Unmarshal(body, &m)
|
err = json.Unmarshal(body, &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -54,7 +54,7 @@ func (c *Client) PackageCreate(f *tpr.Package) (*api.ObjectMeta, error) {
|
|||||||
return &m, nil
|
return &m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) PackageGet(m *api.ObjectMeta) (*tpr.Package, error) {
|
func (c *Client) PackageGet(m *metav1.ObjectMeta) (*crd.Package, error) {
|
||||||
relativeUrl := fmt.Sprintf("packages/%v", m.Name)
|
relativeUrl := fmt.Sprintf("packages/%v", m.Name)
|
||||||
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
||||||
|
|
||||||
@@ -69,7 +69,7 @@ func (c *Client) PackageGet(m *api.ObjectMeta) (*tpr.Package, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var f tpr.Package
|
var f crd.Package
|
||||||
err = json.Unmarshal(body, &f)
|
err = json.Unmarshal(body, &f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -78,7 +78,7 @@ func (c *Client) PackageGet(m *api.ObjectMeta) (*tpr.Package, error) {
|
|||||||
return &f, nil
|
return &f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) PackageUpdate(f *tpr.Package) (*api.ObjectMeta, error) {
|
func (c *Client) PackageUpdate(f *crd.Package) (*metav1.ObjectMeta, error) {
|
||||||
reqbody, err := json.Marshal(f)
|
reqbody, err := json.Marshal(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -96,7 +96,7 @@ func (c *Client) PackageUpdate(f *tpr.Package) (*api.ObjectMeta, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var m api.ObjectMeta
|
var m metav1.ObjectMeta
|
||||||
err = json.Unmarshal(body, &m)
|
err = json.Unmarshal(body, &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -104,13 +104,13 @@ func (c *Client) PackageUpdate(f *tpr.Package) (*api.ObjectMeta, error) {
|
|||||||
return &m, nil
|
return &m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) PackageDelete(m *api.ObjectMeta) error {
|
func (c *Client) PackageDelete(m *metav1.ObjectMeta) error {
|
||||||
relativeUrl := fmt.Sprintf("packages/%v", m.Name)
|
relativeUrl := fmt.Sprintf("packages/%v", m.Name)
|
||||||
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
||||||
return c.delete(relativeUrl)
|
return c.delete(relativeUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) PackageList() ([]tpr.Package, error) {
|
func (c *Client) PackageList() ([]crd.Package, error) {
|
||||||
resp, err := http.Get(c.url("packages"))
|
resp, err := http.Get(c.url("packages"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -122,7 +122,7 @@ func (c *Client) PackageList() ([]tpr.Package, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
funcs := make([]tpr.Package, 0)
|
funcs := make([]crd.Package, 0)
|
||||||
err = json.Unmarshal(body, &funcs)
|
err = json.Unmarshal(body, &funcs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *Client) TimeTriggerCreate(t *tpr.Timetrigger) (*api.ObjectMeta, error) {
|
func (c *Client) TimeTriggerCreate(t *crd.TimeTrigger) (*metav1.ObjectMeta, error) {
|
||||||
reqbody, err := json.Marshal(t)
|
reqbody, err := json.Marshal(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -44,7 +44,7 @@ func (c *Client) TimeTriggerCreate(t *tpr.Timetrigger) (*api.ObjectMeta, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var m api.ObjectMeta
|
var m metav1.ObjectMeta
|
||||||
err = json.Unmarshal(body, &m)
|
err = json.Unmarshal(body, &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -53,7 +53,7 @@ func (c *Client) TimeTriggerCreate(t *tpr.Timetrigger) (*api.ObjectMeta, error)
|
|||||||
return &m, nil
|
return &m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) TimeTriggerGet(m *api.ObjectMeta) (*tpr.Timetrigger, error) {
|
func (c *Client) TimeTriggerGet(m *metav1.ObjectMeta) (*crd.TimeTrigger, error) {
|
||||||
relativeUrl := fmt.Sprintf("triggers/time/%v", m.Name)
|
relativeUrl := fmt.Sprintf("triggers/time/%v", m.Name)
|
||||||
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ func (c *Client) TimeTriggerGet(m *api.ObjectMeta) (*tpr.Timetrigger, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var t tpr.Timetrigger
|
var t crd.TimeTrigger
|
||||||
err = json.Unmarshal(body, &t)
|
err = json.Unmarshal(body, &t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -77,7 +77,7 @@ func (c *Client) TimeTriggerGet(m *api.ObjectMeta) (*tpr.Timetrigger, error) {
|
|||||||
return &t, nil
|
return &t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) TimeTriggerUpdate(t *tpr.Timetrigger) (*api.ObjectMeta, error) {
|
func (c *Client) TimeTriggerUpdate(t *crd.TimeTrigger) (*metav1.ObjectMeta, error) {
|
||||||
reqbody, err := json.Marshal(t)
|
reqbody, err := json.Marshal(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -95,7 +95,7 @@ func (c *Client) TimeTriggerUpdate(t *tpr.Timetrigger) (*api.ObjectMeta, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var m api.ObjectMeta
|
var m metav1.ObjectMeta
|
||||||
err = json.Unmarshal(body, &m)
|
err = json.Unmarshal(body, &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -103,13 +103,13 @@ func (c *Client) TimeTriggerUpdate(t *tpr.Timetrigger) (*api.ObjectMeta, error)
|
|||||||
return &m, nil
|
return &m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) TimeTriggerDelete(m *api.ObjectMeta) error {
|
func (c *Client) TimeTriggerDelete(m *metav1.ObjectMeta) error {
|
||||||
relativeUrl := fmt.Sprintf("triggers/time/%v", m.Name)
|
relativeUrl := fmt.Sprintf("triggers/time/%v", m.Name)
|
||||||
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
relativeUrl += fmt.Sprintf("?namespace=%v", m.Namespace)
|
||||||
return c.delete(relativeUrl)
|
return c.delete(relativeUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) TimeTriggerList() ([]tpr.Timetrigger, error) {
|
func (c *Client) TimeTriggerList() ([]crd.TimeTrigger, error) {
|
||||||
resp, err := http.Get(c.url("triggers/time"))
|
resp, err := http.Get(c.url("triggers/time"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -121,7 +121,7 @@ func (c *Client) TimeTriggerList() ([]tpr.Timetrigger, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
triggers := make([]tpr.Timetrigger, 0)
|
triggers := make([]crd.TimeTrigger, 0)
|
||||||
err = json.Unmarshal(body, &triggers)
|
err = json.Unmarshal(body, &triggers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -19,21 +19,21 @@ package controller
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Start(port int) {
|
func Start(port int) {
|
||||||
fc, kc, err := tpr.MakeFissionClient()
|
fc, _, apiExtClient, err := crd.MakeFissionClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to connect to K8s API: %v", err)
|
log.Fatalf("Failed to connect to K8s API: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = tpr.EnsureFissionTPRs(kc)
|
err = crd.EnsureFissionCRDs(apiExtClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to create fission TPRs: %v", err)
|
log.Fatalf("Failed to create fission CRDs: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fc.WaitForTPRs()
|
fc.WaitForCRDs()
|
||||||
|
|
||||||
api, err := MakeAPI()
|
api, err := MakeAPI()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -20,15 +20,15 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeTPRBackedAPI() (*API, error) {
|
func makeCRDBackedAPI() (*API, error) {
|
||||||
fissionClient, _, err := tpr.MakeFissionClient()
|
fissionClient, kubernetesClient, _, err := crd.MakeFissionClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &API{fissionClient: fissionClient}, nil
|
return &API{fissionClient: fissionClient, kubernetesClient: kubernetesClient}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateResourceName(name string) error {
|
func validateResourceName(name string) error {
|
||||||
@@ -23,14 +23,14 @@ import (
|
|||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *API) EnvironmentApiList(w http.ResponseWriter, r *http.Request) {
|
func (a *API) EnvironmentApiList(w http.ResponseWriter, r *http.Request) {
|
||||||
envs, err := a.fissionClient.Environments(api.NamespaceAll).List(api.ListOptions{})
|
envs, err := a.fissionClient.Environments(metav1.NamespaceAll).List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -52,7 +52,7 @@ func (a *API) EnvironmentApiCreate(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var env tpr.Environment
|
var env crd.Environment
|
||||||
err = json.Unmarshal(body, &env)
|
err = json.Unmarshal(body, &env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to unmarshal request body: [%v]", body)
|
log.Printf("Failed to unmarshal request body: [%v]", body)
|
||||||
@@ -87,7 +87,7 @@ func (a *API) EnvironmentApiGet(w http.ResponseWriter, r *http.Request) {
|
|||||||
name := vars["environment"]
|
name := vars["environment"]
|
||||||
ns := vars["namespace"]
|
ns := vars["namespace"]
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
ns = api.NamespaceDefault
|
ns = metav1.NamespaceDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
env, err := a.fissionClient.Environments(ns).Get(name)
|
env, err := a.fissionClient.Environments(ns).Get(name)
|
||||||
@@ -115,7 +115,7 @@ func (a *API) EnvironmentApiUpdate(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var env tpr.Environment
|
var env crd.Environment
|
||||||
err = json.Unmarshal(body, &env)
|
err = json.Unmarshal(body, &env)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
@@ -148,10 +148,10 @@ func (a *API) EnvironmentApiDelete(w http.ResponseWriter, r *http.Request) {
|
|||||||
name := vars["environment"]
|
name := vars["environment"]
|
||||||
ns := vars["namespace"]
|
ns := vars["namespace"]
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
ns = api.NamespaceDefault
|
ns = metav1.NamespaceDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
err := a.fissionClient.Environments(ns).Delete(name, &api.DeleteOptions{})
|
err := a.fissionClient.Environments(ns).Delete(name, &metav1.DeleteOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -18,21 +18,27 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/client-go/pkg/api"
|
||||||
|
"k8s.io/client-go/pkg/api/v1"
|
||||||
|
restclient "k8s.io/client-go/rest"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *API) FunctionApiList(w http.ResponseWriter, r *http.Request) {
|
func (a *API) FunctionApiList(w http.ResponseWriter, r *http.Request) {
|
||||||
funcs, err := a.fissionClient.Functions(api.NamespaceAll).List(api.ListOptions{})
|
funcs, err := a.fissionClient.Functions(metav1.NamespaceAll).List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -54,7 +60,7 @@ func (a *API) FunctionApiCreate(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var f tpr.Function
|
var f crd.Function
|
||||||
err = json.Unmarshal(body, &f)
|
err = json.Unmarshal(body, &f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
@@ -88,7 +94,7 @@ func (a *API) FunctionApiGet(w http.ResponseWriter, r *http.Request) {
|
|||||||
name := vars["function"]
|
name := vars["function"]
|
||||||
ns := vars["namespace"]
|
ns := vars["namespace"]
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
ns = api.NamespaceDefault
|
ns = metav1.NamespaceDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := a.fissionClient.Functions(ns).Get(name)
|
f, err := a.fissionClient.Functions(ns).Get(name)
|
||||||
@@ -115,7 +121,7 @@ func (a *API) FunctionApiUpdate(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var f tpr.Function
|
var f crd.Function
|
||||||
err = json.Unmarshal(body, &f)
|
err = json.Unmarshal(body, &f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
@@ -147,10 +153,10 @@ func (a *API) FunctionApiDelete(w http.ResponseWriter, r *http.Request) {
|
|||||||
name := vars["function"]
|
name := vars["function"]
|
||||||
ns := vars["namespace"]
|
ns := vars["namespace"]
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
ns = api.NamespaceDefault
|
ns = metav1.NamespaceDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
err := a.fissionClient.Functions(ns).Delete(name, &api.DeleteOptions{})
|
err := a.fissionClient.Functions(ns).Delete(name, &metav1.DeleteOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -188,3 +194,65 @@ func (a *API) FunctionLogsApiPost(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
proxy.ServeHTTP(w, r)
|
proxy.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FunctionPodLogs : Get logs for a function directly from pod
|
||||||
|
func (a *API) FunctionPodLogs(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
fnName := vars["function"]
|
||||||
|
ns := vars["namespace"]
|
||||||
|
|
||||||
|
if len(ns) == 0 {
|
||||||
|
ns = "fission-function"
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := a.fissionClient.Functions(api.NamespaceDefault).Get(fnName)
|
||||||
|
if err != nil {
|
||||||
|
a.respondWithError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
envName := f.Spec.Environment.Name
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
a.respondWithError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get function Pods first
|
||||||
|
selector := "functionName=" + fnName
|
||||||
|
podList, err := a.kubernetesClient.Core().Pods(ns).List(metav1.ListOptions{LabelSelector: selector})
|
||||||
|
if err != nil {
|
||||||
|
a.respondWithError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the logs for last Pod executed
|
||||||
|
pods := podList.Items
|
||||||
|
sort.Slice(pods, func(i, j int) bool {
|
||||||
|
itime := pods[i].ObjectMeta.CreationTimestamp.Time
|
||||||
|
jtime := pods[j].ObjectMeta.CreationTimestamp.Time
|
||||||
|
return itime.After(jtime)
|
||||||
|
})
|
||||||
|
|
||||||
|
podLogOpts := v1.PodLogOptions{Container: envName} // Only the env container, not fetcher
|
||||||
|
var podLogsReq *restclient.Request
|
||||||
|
if len(pods) > 0 {
|
||||||
|
podLogsReq = a.kubernetesClient.Core().Pods(ns).GetLogs(pods[0].ObjectMeta.Name, &podLogOpts)
|
||||||
|
} else {
|
||||||
|
a.respondWithError(w, errors.New("No active pods found"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
podLogs, err := podLogsReq.Stream()
|
||||||
|
if err != nil {
|
||||||
|
a.respondWithError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer podLogs.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(w, podLogs)
|
||||||
|
if err != nil {
|
||||||
|
a.respondWithError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *API) HTTPTriggerApiList(w http.ResponseWriter, r *http.Request) {
|
func (a *API) HTTPTriggerApiList(w http.ResponseWriter, r *http.Request) {
|
||||||
triggers, err := a.fissionClient.Httptriggers(api.NamespaceAll).List(api.ListOptions{})
|
triggers, err := a.fissionClient.HTTPTriggers(metav1.NamespaceAll).List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -45,15 +45,15 @@ func (a *API) HTTPTriggerApiList(w http.ResponseWriter, r *http.Request) {
|
|||||||
a.respondWithSuccess(w, resp)
|
a.respondWithSuccess(w, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) checkHttpTriggerDuplicates(t *tpr.Httptrigger) error {
|
func (a *API) checkHTTPTriggerDuplicates(t *crd.HTTPTrigger) error {
|
||||||
triggers, err := a.fissionClient.Httptriggers(api.NamespaceAll).List(api.ListOptions{})
|
triggers, err := a.fissionClient.HTTPTriggers(metav1.NamespaceAll).List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, ht := range triggers.Items {
|
for _, ht := range triggers.Items {
|
||||||
if ht.Spec.RelativeURL == t.Spec.RelativeURL && ht.Spec.Method == t.Spec.Method {
|
if ht.Spec.RelativeURL == t.Spec.RelativeURL && ht.Spec.Method == t.Spec.Method && ht.Spec.Host == t.Spec.Host {
|
||||||
return fission.MakeError(fission.ErrorNameExists,
|
return fission.MakeError(fission.ErrorNameExists,
|
||||||
fmt.Sprintf("HTTPTrigger with same URL & method already exists (%v)",
|
fmt.Sprintf("HTTPTrigger with same Host, URL & method already exists (%v)",
|
||||||
ht.Metadata.Name))
|
ht.Metadata.Name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ func (a *API) HTTPTriggerApiCreate(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var t tpr.Httptrigger
|
var t crd.HTTPTrigger
|
||||||
err = json.Unmarshal(body, &t)
|
err = json.Unmarshal(body, &t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
@@ -81,13 +81,13 @@ func (a *API) HTTPTriggerApiCreate(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we don't have a duplicate HTTP route defined (same URL and method)
|
// Ensure we don't have a duplicate HTTP route defined (same URL and method)
|
||||||
err = a.checkHttpTriggerDuplicates(&t)
|
err = a.checkHTTPTriggerDuplicates(&t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tnew, err := a.fissionClient.Httptriggers(t.Metadata.Namespace).Create(&t)
|
tnew, err := a.fissionClient.HTTPTriggers(t.Metadata.Namespace).Create(&t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -108,10 +108,10 @@ func (a *API) HTTPTriggerApiGet(w http.ResponseWriter, r *http.Request) {
|
|||||||
name := vars["httpTrigger"]
|
name := vars["httpTrigger"]
|
||||||
ns := vars["namespace"]
|
ns := vars["namespace"]
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
ns = api.NamespaceDefault
|
ns = metav1.NamespaceDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
t, err := a.fissionClient.Httptriggers(ns).Get(name)
|
t, err := a.fissionClient.HTTPTriggers(ns).Get(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -136,7 +136,7 @@ func (a *API) HTTPTriggerApiUpdate(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var t tpr.Httptrigger
|
var t crd.HTTPTrigger
|
||||||
err = json.Unmarshal(body, &t)
|
err = json.Unmarshal(body, &t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
@@ -149,13 +149,13 @@ func (a *API) HTTPTriggerApiUpdate(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = a.checkHttpTriggerDuplicates(&t)
|
err = a.checkHTTPTriggerDuplicates(&t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tnew, err := a.fissionClient.Httptriggers(t.Metadata.Namespace).Update(&t)
|
tnew, err := a.fissionClient.HTTPTriggers(t.Metadata.Namespace).Update(&t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -174,10 +174,10 @@ func (a *API) HTTPTriggerApiDelete(w http.ResponseWriter, r *http.Request) {
|
|||||||
name := vars["httpTrigger"]
|
name := vars["httpTrigger"]
|
||||||
ns := vars["namespace"]
|
ns := vars["namespace"]
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
ns = api.NamespaceDefault
|
ns = metav1.NamespaceDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
err := a.fissionClient.Httptriggers(ns).Delete(name, &api.DeleteOptions{})
|
err := a.fissionClient.HTTPTriggers(ns).Delete(name, &metav1.DeleteOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
|
|||||||
+11
-11
@@ -22,15 +22,15 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *API) MessageQueueTriggerApiList(w http.ResponseWriter, r *http.Request) {
|
func (a *API) MessageQueueTriggerApiList(w http.ResponseWriter, r *http.Request) {
|
||||||
//mqType := r.FormValue("mqtype") // ignored for now
|
//mqType := r.FormValue("mqtype") // ignored for now
|
||||||
triggers, err := a.fissionClient.Messagequeuetriggers(api.NamespaceAll).List(api.ListOptions{})
|
triggers, err := a.fissionClient.MessageQueueTriggers(metav1.NamespaceAll).List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -50,7 +50,7 @@ func (a *API) MessageQueueTriggerApiCreate(w http.ResponseWriter, r *http.Reques
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var mqTrigger tpr.Messagequeuetrigger
|
var mqTrigger crd.MessageQueueTrigger
|
||||||
err = json.Unmarshal(body, &mqTrigger)
|
err = json.Unmarshal(body, &mqTrigger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
@@ -63,7 +63,7 @@ func (a *API) MessageQueueTriggerApiCreate(w http.ResponseWriter, r *http.Reques
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tnew, err := a.fissionClient.Messagequeuetriggers(mqTrigger.Metadata.Namespace).Create(&mqTrigger)
|
tnew, err := a.fissionClient.MessageQueueTriggers(mqTrigger.Metadata.Namespace).Create(&mqTrigger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -83,10 +83,10 @@ func (a *API) MessageQueueTriggerApiGet(w http.ResponseWriter, r *http.Request)
|
|||||||
name := vars["mqTrigger"]
|
name := vars["mqTrigger"]
|
||||||
ns := vars["namespace"]
|
ns := vars["namespace"]
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
ns = api.NamespaceDefault
|
ns = metav1.NamespaceDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
mqTrigger, err := a.fissionClient.Messagequeuetriggers(ns).Get(name)
|
mqTrigger, err := a.fissionClient.MessageQueueTriggers(ns).Get(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -109,7 +109,7 @@ func (a *API) MessageQueueTriggerApiUpdate(w http.ResponseWriter, r *http.Reques
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var mqTrigger tpr.Messagequeuetrigger
|
var mqTrigger crd.MessageQueueTrigger
|
||||||
err = json.Unmarshal(body, &mqTrigger)
|
err = json.Unmarshal(body, &mqTrigger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
@@ -122,7 +122,7 @@ func (a *API) MessageQueueTriggerApiUpdate(w http.ResponseWriter, r *http.Reques
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tnew, err := a.fissionClient.Messagequeuetriggers(mqTrigger.Metadata.Namespace).Update(&mqTrigger)
|
tnew, err := a.fissionClient.MessageQueueTriggers(mqTrigger.Metadata.Namespace).Update(&mqTrigger)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -141,10 +141,10 @@ func (a *API) MessageQueueTriggerApiDelete(w http.ResponseWriter, r *http.Reques
|
|||||||
name := vars["mqTrigger"]
|
name := vars["mqTrigger"]
|
||||||
ns := vars["namespace"]
|
ns := vars["namespace"]
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
ns = api.NamespaceDefault
|
ns = metav1.NamespaceDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
err := a.fissionClient.Messagequeuetriggers(ns).Delete(name, &api.DeleteOptions{})
|
err := a.fissionClient.MessageQueueTriggers(ns).Delete(name, &metav1.DeleteOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *API) PackageApiList(w http.ResponseWriter, r *http.Request) {
|
func (a *API) PackageApiList(w http.ResponseWriter, r *http.Request) {
|
||||||
funcs, err := a.fissionClient.Packages(api.NamespaceAll).List(api.ListOptions{})
|
funcs, err := a.fissionClient.Packages(metav1.NamespaceAll).List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -51,7 +51,7 @@ func (a *API) PackageApiCreate(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var f tpr.Package
|
var f crd.Package
|
||||||
err = json.Unmarshal(body, &f)
|
err = json.Unmarshal(body, &f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
@@ -97,7 +97,7 @@ func (a *API) PackageApiGet(w http.ResponseWriter, r *http.Request) {
|
|||||||
name := vars["package"]
|
name := vars["package"]
|
||||||
ns := vars["namespace"]
|
ns := vars["namespace"]
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
ns = api.NamespaceDefault
|
ns = metav1.NamespaceDefault
|
||||||
}
|
}
|
||||||
raw := r.FormValue("raw") // just the deployment pkg
|
raw := r.FormValue("raw") // just the deployment pkg
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ func (a *API) PackageApiUpdate(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var f tpr.Package
|
var f crd.Package
|
||||||
err = json.Unmarshal(body, &f)
|
err = json.Unmarshal(body, &f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
@@ -162,10 +162,10 @@ func (a *API) PackageApiDelete(w http.ResponseWriter, r *http.Request) {
|
|||||||
name := vars["package"]
|
name := vars["package"]
|
||||||
ns := vars["namespace"]
|
ns := vars["namespace"]
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
ns = api.NamespaceDefault
|
ns = metav1.NamespaceDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
err := a.fissionClient.Packages(ns).Delete(name, &api.DeleteOptions{})
|
err := a.fissionClient.Packages(ns).Delete(name, &metav1.DeleteOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -23,14 +23,14 @@ import (
|
|||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/robfig/cron"
|
"github.com/robfig/cron"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *API) TimeTriggerApiList(w http.ResponseWriter, r *http.Request) {
|
func (a *API) TimeTriggerApiList(w http.ResponseWriter, r *http.Request) {
|
||||||
triggers, err := a.fissionClient.Timetriggers(api.NamespaceAll).List(api.ListOptions{})
|
triggers, err := a.fissionClient.TimeTriggers(metav1.NamespaceAll).List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -52,7 +52,7 @@ func (a *API) TimeTriggerApiCreate(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var t tpr.Timetrigger
|
var t crd.TimeTrigger
|
||||||
err = json.Unmarshal(body, &t)
|
err = json.Unmarshal(body, &t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
@@ -73,7 +73,7 @@ func (a *API) TimeTriggerApiCreate(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tnew, err := a.fissionClient.Timetriggers(t.Metadata.Namespace).Create(&t)
|
tnew, err := a.fissionClient.TimeTriggers(t.Metadata.Namespace).Create(&t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -94,10 +94,10 @@ func (a *API) TimeTriggerApiGet(w http.ResponseWriter, r *http.Request) {
|
|||||||
name := vars["timeTrigger"]
|
name := vars["timeTrigger"]
|
||||||
ns := vars["namespace"]
|
ns := vars["namespace"]
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
ns = api.NamespaceDefault
|
ns = metav1.NamespaceDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
t, err := a.fissionClient.Timetriggers(ns).Get(name)
|
t, err := a.fissionClient.TimeTriggers(ns).Get(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -122,7 +122,7 @@ func (a *API) TimeTriggerApiUpdate(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var t tpr.Timetrigger
|
var t crd.TimeTrigger
|
||||||
err = json.Unmarshal(body, &t)
|
err = json.Unmarshal(body, &t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
@@ -142,7 +142,7 @@ func (a *API) TimeTriggerApiUpdate(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tnew, err := a.fissionClient.Timetriggers(t.Metadata.Namespace).Update(&t)
|
tnew, err := a.fissionClient.TimeTriggers(t.Metadata.Namespace).Update(&t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -161,10 +161,10 @@ func (a *API) TimeTriggerApiDelete(w http.ResponseWriter, r *http.Request) {
|
|||||||
name := vars["timeTrigger"]
|
name := vars["timeTrigger"]
|
||||||
ns := vars["namespace"]
|
ns := vars["namespace"]
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
ns = api.NamespaceDefault
|
ns = metav1.NamespaceDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
err := a.fissionClient.Timetriggers(ns).Delete(name, &api.DeleteOptions{})
|
err := a.fissionClient.TimeTriggers(ns).Delete(name, &metav1.DeleteOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
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 controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
"github.com/fission/fission/crd"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *API) Tpr2crdApi(w http.ResponseWriter, r *http.Request) {
|
||||||
|
_, kubeClient, _, err := crd.MakeFissionClient()
|
||||||
|
if err != nil {
|
||||||
|
a.respondWithError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fissionTprs := []string{
|
||||||
|
"function.fission.io",
|
||||||
|
"environment.fission.io",
|
||||||
|
"httptrigger.fission.io",
|
||||||
|
"kuberneteswatchtrigger.fission.io",
|
||||||
|
"timetrigger.fission.io",
|
||||||
|
"messagequeuetrigger.fission.io",
|
||||||
|
"package.fission.io",
|
||||||
|
}
|
||||||
|
|
||||||
|
tprList, err := kubeClient.ThirdPartyResources().List(metav1.ListOptions{})
|
||||||
|
if err != nil {
|
||||||
|
a.respondWithError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tpr := range tprList.Items {
|
||||||
|
for _, tprName := range fissionTprs {
|
||||||
|
if tpr.Name == tprName {
|
||||||
|
err := kubeClient.ThirdPartyResources().Delete(tpr.Name, &metav1.DeleteOptions{})
|
||||||
|
if err != nil {
|
||||||
|
a.respondWithError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a.respondWithSuccess(w, nil)
|
||||||
|
}
|
||||||
@@ -22,14 +22,14 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *API) WatchApiList(w http.ResponseWriter, r *http.Request) {
|
func (a *API) WatchApiList(w http.ResponseWriter, r *http.Request) {
|
||||||
watches, err := a.fissionClient.Kuberneteswatchtriggers(api.NamespaceAll).List(api.ListOptions{})
|
watches, err := a.fissionClient.KubernetesWatchTriggers(metav1.NamespaceAll).List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -51,7 +51,7 @@ func (a *API) WatchApiCreate(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var watch tpr.Kuberneteswatchtrigger
|
var watch crd.KubernetesWatchTrigger
|
||||||
err = json.Unmarshal(body, &watch)
|
err = json.Unmarshal(body, &watch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
@@ -66,7 +66,7 @@ func (a *API) WatchApiCreate(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// TODO check for duplicate watches
|
// TODO check for duplicate watches
|
||||||
|
|
||||||
wnew, err := a.fissionClient.Kuberneteswatchtriggers(watch.Metadata.Namespace).Create(&watch)
|
wnew, err := a.fissionClient.KubernetesWatchTriggers(watch.Metadata.Namespace).Create(&watch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -87,10 +87,10 @@ func (a *API) WatchApiGet(w http.ResponseWriter, r *http.Request) {
|
|||||||
name := vars["watch"]
|
name := vars["watch"]
|
||||||
ns := vars["namespace"]
|
ns := vars["namespace"]
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
ns = api.NamespaceDefault
|
ns = metav1.NamespaceDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
watch, err := a.fissionClient.Kuberneteswatchtriggers(ns).Get(name)
|
watch, err := a.fissionClient.KubernetesWatchTriggers(ns).Get(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
@@ -115,10 +115,10 @@ func (a *API) WatchApiDelete(w http.ResponseWriter, r *http.Request) {
|
|||||||
name := vars["watch"]
|
name := vars["watch"]
|
||||||
ns := vars["namespace"]
|
ns := vars["namespace"]
|
||||||
if len(ns) == 0 {
|
if len(ns) == 0 {
|
||||||
ns = api.NamespaceDefault
|
ns = metav1.NamespaceDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
err := a.fissionClient.Kuberneteswatchtriggers(ns).Delete(name, &api.DeleteOptions{})
|
err := a.fissionClient.KubernetesWatchTriggers(ns).Delete(name, &metav1.DeleteOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.respondWithError(w, err)
|
a.respondWithError(w, err)
|
||||||
return
|
return
|
||||||
|
|||||||
+220
@@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
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 crd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
|
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
FissionClient struct {
|
||||||
|
crdClient *rest.RESTClient
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Get a kubernetes client using the kubeconfig file at the
|
||||||
|
// environment var $KUBECONFIG, or an in-cluster config if that's
|
||||||
|
// undefined.
|
||||||
|
func GetKubernetesClient() (*rest.Config, *kubernetes.Clientset, *apiextensionsclient.Clientset, error) {
|
||||||
|
var config *rest.Config
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// get the config, either from kubeconfig or using our
|
||||||
|
// in-cluster service account
|
||||||
|
kubeConfig := os.Getenv("KUBECONFIG")
|
||||||
|
if len(kubeConfig) != 0 {
|
||||||
|
config, err = clientcmd.BuildConfigFromFlags("", kubeConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
config, err = rest.InClusterConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// creates the clientset
|
||||||
|
clientset, err := kubernetes.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
apiExtClientset, err := apiextensionsclient.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return config, clientset, apiExtClientset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCrdClient gets a CRD client config
|
||||||
|
func GetCrdClient(config *rest.Config) (*rest.RESTClient, error) {
|
||||||
|
// mutate config to add our types
|
||||||
|
configureClient(config)
|
||||||
|
|
||||||
|
// make a REST client with that config
|
||||||
|
return rest.RESTClientFor(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
// configureClient sets up a REST client for Fission CRD types.
|
||||||
|
//
|
||||||
|
// This is copied from the client-go CRD example. (I don't understand
|
||||||
|
// all of it completely.) It registers our types with the global API
|
||||||
|
// "scheme" (api.Scheme), which keeps a directory of types [I guess so
|
||||||
|
// it can use the string in the Kind field to make a Go object?]. It
|
||||||
|
// also puts the fission CRD types under a "group version" which we
|
||||||
|
// create for our CRDs types.
|
||||||
|
func configureClient(config *rest.Config) {
|
||||||
|
groupversion := schema.GroupVersion{
|
||||||
|
Group: "fission.io",
|
||||||
|
Version: "v1",
|
||||||
|
}
|
||||||
|
config.GroupVersion = &groupversion
|
||||||
|
config.APIPath = "/apis"
|
||||||
|
config.ContentType = runtime.ContentTypeJSON
|
||||||
|
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
|
||||||
|
|
||||||
|
schemeBuilder := runtime.NewSchemeBuilder(
|
||||||
|
func(scheme *runtime.Scheme) error {
|
||||||
|
scheme.AddKnownTypes(
|
||||||
|
groupversion,
|
||||||
|
&Function{},
|
||||||
|
&FunctionList{},
|
||||||
|
&metav1.ListOptions{},
|
||||||
|
&metav1.DeleteOptions{},
|
||||||
|
)
|
||||||
|
scheme.AddKnownTypes(
|
||||||
|
groupversion,
|
||||||
|
&Environment{},
|
||||||
|
&EnvironmentList{},
|
||||||
|
&metav1.ListOptions{},
|
||||||
|
&metav1.DeleteOptions{},
|
||||||
|
)
|
||||||
|
scheme.AddKnownTypes(
|
||||||
|
groupversion,
|
||||||
|
&HTTPTrigger{},
|
||||||
|
&HTTPTriggerList{},
|
||||||
|
&metav1.ListOptions{},
|
||||||
|
&metav1.DeleteOptions{},
|
||||||
|
)
|
||||||
|
scheme.AddKnownTypes(
|
||||||
|
groupversion,
|
||||||
|
&KubernetesWatchTrigger{},
|
||||||
|
&KubernetesWatchTriggerList{},
|
||||||
|
&metav1.ListOptions{},
|
||||||
|
&metav1.DeleteOptions{},
|
||||||
|
)
|
||||||
|
scheme.AddKnownTypes(
|
||||||
|
groupversion,
|
||||||
|
&TimeTrigger{},
|
||||||
|
&TimeTriggerList{},
|
||||||
|
&metav1.ListOptions{},
|
||||||
|
&metav1.DeleteOptions{},
|
||||||
|
)
|
||||||
|
scheme.AddKnownTypes(
|
||||||
|
groupversion,
|
||||||
|
&MessageQueueTrigger{},
|
||||||
|
&MessageQueueTriggerList{},
|
||||||
|
&metav1.ListOptions{},
|
||||||
|
&metav1.DeleteOptions{},
|
||||||
|
)
|
||||||
|
scheme.AddKnownTypes(
|
||||||
|
groupversion,
|
||||||
|
&Package{},
|
||||||
|
&PackageList{},
|
||||||
|
&metav1.ListOptions{},
|
||||||
|
&metav1.DeleteOptions{},
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
schemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
func waitForCRDs(crdClient *rest.RESTClient) error {
|
||||||
|
start := time.Now()
|
||||||
|
for {
|
||||||
|
fi := MakeFunctionInterface(crdClient, metav1.NamespaceDefault)
|
||||||
|
_, err := fi.List(metav1.ListOptions{})
|
||||||
|
if err != nil {
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if time.Now().Sub(start) > 30*time.Second {
|
||||||
|
return errors.New("timeout waiting for CRDs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeFissionClient() (*FissionClient, *kubernetes.Clientset, *apiextensionsclient.Clientset, error) {
|
||||||
|
config, kubeClient, apiExtClient, err := GetKubernetesClient()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
crdClient, err := GetCrdClient(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, err
|
||||||
|
}
|
||||||
|
fc := &FissionClient{
|
||||||
|
crdClient: crdClient,
|
||||||
|
}
|
||||||
|
return fc, kubeClient, apiExtClient, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fc *FissionClient) Functions(ns string) FunctionInterface {
|
||||||
|
return MakeFunctionInterface(fc.crdClient, ns)
|
||||||
|
}
|
||||||
|
func (fc *FissionClient) Environments(ns string) EnvironmentInterface {
|
||||||
|
return MakeEnvironmentInterface(fc.crdClient, ns)
|
||||||
|
}
|
||||||
|
func (fc *FissionClient) HTTPTriggers(ns string) HTTPTriggerInterface {
|
||||||
|
return MakeHTTPTriggerInterface(fc.crdClient, ns)
|
||||||
|
}
|
||||||
|
func (fc *FissionClient) KubernetesWatchTriggers(ns string) KubernetesWatchTriggerInterface {
|
||||||
|
return MakeKubernetesWatchTriggerInterface(fc.crdClient, ns)
|
||||||
|
}
|
||||||
|
func (fc *FissionClient) TimeTriggers(ns string) TimeTriggerInterface {
|
||||||
|
return MakeTimeTriggerInterface(fc.crdClient, ns)
|
||||||
|
}
|
||||||
|
func (fc *FissionClient) MessageQueueTriggers(ns string) MessageQueueTriggerInterface {
|
||||||
|
return MakeMessageQueueTriggerInterface(fc.crdClient, ns)
|
||||||
|
}
|
||||||
|
func (fc *FissionClient) Packages(ns string) PackageInterface {
|
||||||
|
return MakePackageInterface(fc.crdClient, ns)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fc *FissionClient) WaitForCRDs() {
|
||||||
|
waitForCRDs(fc.crdClient)
|
||||||
|
}
|
||||||
|
func (fc *FissionClient) GetCrdClient() *rest.RESTClient {
|
||||||
|
return fc.crdClient
|
||||||
|
}
|
||||||
+170
@@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
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 crd
|
||||||
|
|
||||||
|
import (
|
||||||
|
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||||
|
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
crdGroupName = "fission.io"
|
||||||
|
crdVersion = "v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ensureCRD checks if the given CRD type exists, and creates it if
|
||||||
|
// needed. (Note that this creates the CRD type; it doesn't create any
|
||||||
|
// _instances_ of that type.)
|
||||||
|
func ensureCRD(clientset *apiextensionsclient.Clientset, crd *apiextensionsv1beta1.CustomResourceDefinition) error {
|
||||||
|
_, err := clientset.Apiextensions().CustomResourceDefinitions().Get(crd.ObjectMeta.Name, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
if errors.IsNotFound(err) {
|
||||||
|
_, err := clientset.Apiextensions().CustomResourceDefinitions().Create(crd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure CRDs
|
||||||
|
func EnsureFissionCRDs(clientset *apiextensionsclient.Clientset) error {
|
||||||
|
crds := []apiextensionsv1beta1.CustomResourceDefinition{
|
||||||
|
// Functions
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "functions.fission.io",
|
||||||
|
},
|
||||||
|
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||||
|
Group: crdGroupName,
|
||||||
|
Version: crdVersion,
|
||||||
|
Scope: apiextensionsv1beta1.NamespaceScoped,
|
||||||
|
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||||
|
Kind: "Function",
|
||||||
|
Plural: "functions",
|
||||||
|
Singular: "function",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Environments (function containers)
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "environments.fission.io",
|
||||||
|
},
|
||||||
|
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||||
|
Group: crdGroupName,
|
||||||
|
Version: crdVersion,
|
||||||
|
Scope: apiextensionsv1beta1.NamespaceScoped,
|
||||||
|
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||||
|
Kind: "Environment",
|
||||||
|
Plural: "environments",
|
||||||
|
Singular: "environment",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// HTTP triggers for functions
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "httptriggers.fission.io",
|
||||||
|
},
|
||||||
|
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||||
|
Group: crdGroupName,
|
||||||
|
Version: crdVersion,
|
||||||
|
Scope: apiextensionsv1beta1.NamespaceScoped,
|
||||||
|
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||||
|
Kind: "HTTPTrigger",
|
||||||
|
Plural: "httptriggers",
|
||||||
|
Singular: "httptrigger",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Kubernetes watch triggers for functions
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "kuberneteswatchtriggers.fission.io",
|
||||||
|
},
|
||||||
|
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||||
|
Group: crdGroupName,
|
||||||
|
Version: crdVersion,
|
||||||
|
Scope: apiextensionsv1beta1.NamespaceScoped,
|
||||||
|
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||||
|
Kind: "KubernetesWatchTrigger",
|
||||||
|
Plural: "kuberneteswatchtriggers",
|
||||||
|
Singular: "kuberneteswatchtrigger",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Time-based triggers for functions
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "timetriggers.fission.io",
|
||||||
|
},
|
||||||
|
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||||
|
Group: crdGroupName,
|
||||||
|
Version: crdVersion,
|
||||||
|
Scope: apiextensionsv1beta1.NamespaceScoped,
|
||||||
|
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||||
|
Kind: "TimeTrigger",
|
||||||
|
Plural: "timetriggers",
|
||||||
|
Singular: "timetrigger",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Message queue triggers for functions
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "messagequeuetriggers.fission.io",
|
||||||
|
},
|
||||||
|
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||||
|
Group: crdGroupName,
|
||||||
|
Version: crdVersion,
|
||||||
|
Scope: apiextensionsv1beta1.NamespaceScoped,
|
||||||
|
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||||
|
Kind: "MessageQueueTrigger",
|
||||||
|
Plural: "messagequeuetriggers",
|
||||||
|
Singular: "messagequeuetrigger",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Packages: archives containing source or binaries for one or more functions
|
||||||
|
{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "packages.fission.io",
|
||||||
|
},
|
||||||
|
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
|
||||||
|
Group: crdGroupName,
|
||||||
|
Version: crdVersion,
|
||||||
|
Scope: apiextensionsv1beta1.NamespaceScoped,
|
||||||
|
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
|
||||||
|
Kind: "Package",
|
||||||
|
Plural: "packages",
|
||||||
|
Singular: "package",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, crd := range crds {
|
||||||
|
err := ensureCRD(clientset, &crd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package tpr
|
package crd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
@@ -22,9 +22,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/api/unversioned"
|
"k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/1.5/rest"
|
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
)
|
)
|
||||||
@@ -35,15 +34,16 @@ func panicIf(err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func functionTests(tprClient *rest.RESTClient) {
|
func functionTests(crdClient *rest.RESTClient) {
|
||||||
// sample function object
|
// sample function object
|
||||||
function := &Function{
|
function := &Function{
|
||||||
TypeMeta: unversioned.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
Kind: "Function",
|
Kind: "Function",
|
||||||
APIVersion: "fission.io/v1",
|
APIVersion: "fission.io/v1",
|
||||||
},
|
},
|
||||||
Metadata: api.ObjectMeta{
|
Metadata: metav1.ObjectMeta{
|
||||||
Name: "hello",
|
Name: "hello",
|
||||||
|
Namespace: metav1.NamespaceDefault,
|
||||||
},
|
},
|
||||||
Spec: fission.FunctionSpec{
|
Spec: fission.FunctionSpec{
|
||||||
Package: fission.FunctionPackageRef{
|
Package: fission.FunctionPackageRef{
|
||||||
@@ -60,7 +60,7 @@ func functionTests(tprClient *rest.RESTClient) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test function CRUD
|
// Test function CRUD
|
||||||
fi := MakeFunctionInterface(tprClient, api.NamespaceDefault)
|
fi := MakeFunctionInterface(crdClient, metav1.NamespaceDefault)
|
||||||
|
|
||||||
// cleanup from old crashed tests, ignore errors
|
// cleanup from old crashed tests, ignore errors
|
||||||
fi.Delete(function.Metadata.Name, nil)
|
fi.Delete(function.Metadata.Name, nil)
|
||||||
@@ -82,6 +82,7 @@ func functionTests(tprClient *rest.RESTClient) {
|
|||||||
log.Printf("f.Metadata = %#v", f.Metadata)
|
log.Printf("f.Metadata = %#v", f.Metadata)
|
||||||
|
|
||||||
// update
|
// update
|
||||||
|
function.Metadata.ResourceVersion = f.Metadata.ResourceVersion
|
||||||
function.Spec.Environment.Name = "yyy"
|
function.Spec.Environment.Name = "yyy"
|
||||||
f, err = fi.Update(function)
|
f, err = fi.Update(function)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
@@ -89,12 +90,12 @@ func functionTests(tprClient *rest.RESTClient) {
|
|||||||
log.Printf("f.Metadata = %#v", f.Metadata)
|
log.Printf("f.Metadata = %#v", f.Metadata)
|
||||||
|
|
||||||
// list
|
// list
|
||||||
fl, err := fi.List(api.ListOptions{})
|
fl, err := fi.List(metav1.ListOptions{})
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
if len(fl.Items) != 1 {
|
if len(fl.Items) != 1 {
|
||||||
log.Panicf("wrong count from list: %v", fl)
|
log.Panicf("wrong count from function list: %v", len(fl.Items))
|
||||||
}
|
}
|
||||||
if fl.Items[0].Spec.Environment.Name != function.Spec.Environment.Name {
|
if fl.Items[0].Spec.Environment.Name != f.Spec.Environment.Name {
|
||||||
log.Panicf("bad object from list: %v", fl.Items[0])
|
log.Panicf("bad object from list: %v", fl.Items[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,10 +104,11 @@ func functionTests(tprClient *rest.RESTClient) {
|
|||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
// start a watch
|
// start a watch
|
||||||
wi, err := fi.Watch(api.ListOptions{})
|
wi, err := fi.Watch(metav1.ListOptions{})
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
function.Metadata.ResourceVersion = ""
|
||||||
f, err = fi.Create(function)
|
f, err = fi.Create(function)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
defer fi.Delete(f.Metadata.Name, nil)
|
defer fi.Delete(f.Metadata.Name, nil)
|
||||||
@@ -132,15 +134,16 @@ func functionTests(tprClient *rest.RESTClient) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func environmentTests(tprClient *rest.RESTClient) {
|
func environmentTests(crdClient *rest.RESTClient) {
|
||||||
// sample environment object
|
// sample environment object
|
||||||
environment := &Environment{
|
environment := &Environment{
|
||||||
TypeMeta: unversioned.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
Kind: "Environment",
|
Kind: "Environment",
|
||||||
APIVersion: "fission.io/v1",
|
APIVersion: "fission.io/v1",
|
||||||
},
|
},
|
||||||
Metadata: api.ObjectMeta{
|
Metadata: metav1.ObjectMeta{
|
||||||
Name: "hello",
|
Name: "hello",
|
||||||
|
Namespace: metav1.NamespaceDefault,
|
||||||
},
|
},
|
||||||
Spec: fission.EnvironmentSpec{
|
Spec: fission.EnvironmentSpec{
|
||||||
Runtime: fission.Runtime{
|
Runtime: fission.Runtime{
|
||||||
@@ -154,7 +157,7 @@ func environmentTests(tprClient *rest.RESTClient) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test environment CRUD
|
// Test environment CRUD
|
||||||
ei := MakeEnvironmentInterface(tprClient, api.NamespaceDefault)
|
ei := MakeEnvironmentInterface(crdClient, metav1.NamespaceDefault)
|
||||||
|
|
||||||
// cleanup from old crashed tests, ignore errors
|
// cleanup from old crashed tests, ignore errors
|
||||||
ei.Delete(environment.Metadata.Name, nil)
|
ei.Delete(environment.Metadata.Name, nil)
|
||||||
@@ -174,17 +177,18 @@ func environmentTests(tprClient *rest.RESTClient) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update
|
// update
|
||||||
|
environment.Metadata.ResourceVersion = e.Metadata.ResourceVersion
|
||||||
environment.Spec.Runtime.Image = "www"
|
environment.Spec.Runtime.Image = "www"
|
||||||
e, err = ei.Update(environment)
|
e, err = ei.Update(environment)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
// list
|
// list
|
||||||
el, err := ei.List(api.ListOptions{})
|
el, err := ei.List(metav1.ListOptions{})
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
if len(el.Items) != 1 {
|
if len(el.Items) != 1 {
|
||||||
log.Panicf("wrong count from list: %v", len(el.Items))
|
log.Panicf("wrong count from environment list: %v", len(el.Items))
|
||||||
}
|
}
|
||||||
if el.Items[0].Spec.Runtime.Image != environment.Spec.Runtime.Image {
|
if el.Items[0].Spec.Runtime.Image != e.Spec.Runtime.Image {
|
||||||
log.Panicf("bad object from list: %v", el.Items[0])
|
log.Panicf("bad object from list: %v", el.Items[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,10 +197,11 @@ func environmentTests(tprClient *rest.RESTClient) {
|
|||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
// start a watch
|
// start a watch
|
||||||
wi, err := ei.Watch(api.ListOptions{})
|
wi, err := ei.Watch(metav1.ListOptions{})
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
environment.Metadata.ResourceVersion = ""
|
||||||
e, err = ei.Create(environment)
|
e, err = ei.Create(environment)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
defer ei.Delete(e.Metadata.Name, nil)
|
defer ei.Delete(e.Metadata.Name, nil)
|
||||||
@@ -222,15 +227,16 @@ func environmentTests(tprClient *rest.RESTClient) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func httpTriggerTests(tprClient *rest.RESTClient) {
|
func httpTriggerTests(crdClient *rest.RESTClient) {
|
||||||
// sample httpTrigger object
|
// sample httpTrigger object
|
||||||
httpTrigger := &Httptrigger{
|
httpTrigger := &HTTPTrigger{
|
||||||
TypeMeta: unversioned.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
Kind: "Httptrigger",
|
Kind: "HTTPTrigger",
|
||||||
APIVersion: "fission.io/v1",
|
APIVersion: "fission.io/v1",
|
||||||
},
|
},
|
||||||
Metadata: api.ObjectMeta{
|
Metadata: metav1.ObjectMeta{
|
||||||
Name: "hello",
|
Name: "hello",
|
||||||
|
Namespace: metav1.NamespaceDefault,
|
||||||
},
|
},
|
||||||
Spec: fission.HTTPTriggerSpec{
|
Spec: fission.HTTPTriggerSpec{
|
||||||
RelativeURL: "/hi",
|
RelativeURL: "/hi",
|
||||||
@@ -243,7 +249,7 @@ func httpTriggerTests(tprClient *rest.RESTClient) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test httpTrigger CRUD
|
// Test httpTrigger CRUD
|
||||||
ei := MakeHttptriggerInterface(tprClient, api.NamespaceDefault)
|
ei := MakeHTTPTriggerInterface(crdClient, metav1.NamespaceDefault)
|
||||||
|
|
||||||
// cleanup from old crashed tests, ignore errors
|
// cleanup from old crashed tests, ignore errors
|
||||||
ei.Delete(httpTrigger.Metadata.Name, nil)
|
ei.Delete(httpTrigger.Metadata.Name, nil)
|
||||||
@@ -263,17 +269,18 @@ func httpTriggerTests(tprClient *rest.RESTClient) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update
|
// update
|
||||||
|
httpTrigger.Metadata.ResourceVersion = e.Metadata.ResourceVersion
|
||||||
httpTrigger.Spec.Method = "POST"
|
httpTrigger.Spec.Method = "POST"
|
||||||
e, err = ei.Update(httpTrigger)
|
e, err = ei.Update(httpTrigger)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
// list
|
// list
|
||||||
el, err := ei.List(api.ListOptions{})
|
el, err := ei.List(metav1.ListOptions{})
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
if len(el.Items) != 1 {
|
if len(el.Items) != 1 {
|
||||||
log.Panicf("wrong count from list: %v", el)
|
log.Panicf("wrong count from http trigger list: %v", len(el.Items))
|
||||||
}
|
}
|
||||||
if el.Items[0].Spec.Method != httpTrigger.Spec.Method {
|
if el.Items[0].Spec.Method != e.Spec.Method {
|
||||||
log.Panicf("bad object from list: %v", el.Items[0])
|
log.Panicf("bad object from list: %v", el.Items[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,10 +289,11 @@ func httpTriggerTests(tprClient *rest.RESTClient) {
|
|||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
// start a watch
|
// start a watch
|
||||||
wi, err := ei.Watch(api.ListOptions{})
|
wi, err := ei.Watch(metav1.ListOptions{})
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
httpTrigger.Metadata.ResourceVersion = ""
|
||||||
e, err = ei.Create(httpTrigger)
|
e, err = ei.Create(httpTrigger)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
defer ei.Delete(e.Metadata.Name, nil)
|
defer ei.Delete(e.Metadata.Name, nil)
|
||||||
@@ -298,9 +306,9 @@ func httpTriggerTests(tprClient *rest.RESTClient) {
|
|||||||
log.Panicf("Didn't get watch event")
|
log.Panicf("Didn't get watch event")
|
||||||
}
|
}
|
||||||
case ev := <-wi.ResultChan():
|
case ev := <-wi.ResultChan():
|
||||||
obj, ok := ev.Object.(*Httptrigger)
|
obj, ok := ev.Object.(*HTTPTrigger)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Panicf("Can't cast to Httptrigger")
|
log.Panicf("Can't cast to HTTPTrigger")
|
||||||
}
|
}
|
||||||
if obj.Spec.Method != httpTrigger.Spec.Method {
|
if obj.Spec.Method != httpTrigger.Spec.Method {
|
||||||
log.Panicf("Bad object from watch: %#v", obj)
|
log.Panicf("Bad object from watch: %#v", obj)
|
||||||
@@ -311,15 +319,16 @@ func httpTriggerTests(tprClient *rest.RESTClient) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func kubernetesWatchTriggerTests(tprClient *rest.RESTClient) {
|
func kubernetesWatchTriggerTests(crdClient *rest.RESTClient) {
|
||||||
// sample kubernetesWatchTrigger object
|
// sample kubernetesWatchTrigger object
|
||||||
kubernetesWatchTrigger := &Kuberneteswatchtrigger{
|
kubernetesWatchTrigger := &KubernetesWatchTrigger{
|
||||||
TypeMeta: unversioned.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
Kind: "Kuberneteswatchtrigger",
|
Kind: "KubernetesWatchTrigger",
|
||||||
APIVersion: "fission.io/v1",
|
APIVersion: "fission.io/v1",
|
||||||
},
|
},
|
||||||
Metadata: api.ObjectMeta{
|
Metadata: metav1.ObjectMeta{
|
||||||
Name: "hello",
|
Name: "hello",
|
||||||
|
Namespace: metav1.NamespaceDefault,
|
||||||
},
|
},
|
||||||
Spec: fission.KubernetesWatchTriggerSpec{
|
Spec: fission.KubernetesWatchTriggerSpec{
|
||||||
Namespace: "foo",
|
Namespace: "foo",
|
||||||
@@ -335,7 +344,7 @@ func kubernetesWatchTriggerTests(tprClient *rest.RESTClient) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test kubernetesWatchTrigger CRUD
|
// Test kubernetesWatchTrigger CRUD
|
||||||
ei := MakeKuberneteswatchtriggerInterface(tprClient, api.NamespaceDefault)
|
ei := MakeKubernetesWatchTriggerInterface(crdClient, metav1.NamespaceDefault)
|
||||||
|
|
||||||
// cleanup from old crashed tests, ignore errors
|
// cleanup from old crashed tests, ignore errors
|
||||||
ei.Delete(kubernetesWatchTrigger.Metadata.Name, nil)
|
ei.Delete(kubernetesWatchTrigger.Metadata.Name, nil)
|
||||||
@@ -355,17 +364,18 @@ func kubernetesWatchTriggerTests(tprClient *rest.RESTClient) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update
|
// update
|
||||||
|
kubernetesWatchTrigger.Metadata.ResourceVersion = e.Metadata.ResourceVersion
|
||||||
kubernetesWatchTrigger.Spec.Type = "service"
|
kubernetesWatchTrigger.Spec.Type = "service"
|
||||||
e, err = ei.Update(kubernetesWatchTrigger)
|
e, err = ei.Update(kubernetesWatchTrigger)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
// list
|
// list
|
||||||
el, err := ei.List(api.ListOptions{})
|
el, err := ei.List(metav1.ListOptions{})
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
if len(el.Items) != 1 {
|
if len(el.Items) != 1 {
|
||||||
log.Panicf("wrong count from list: %v", el)
|
log.Panicf("wrong count from kubeWatcher list: %v", len(el.Items))
|
||||||
}
|
}
|
||||||
if el.Items[0].Spec.Type != kubernetesWatchTrigger.Spec.Type {
|
if el.Items[0].Spec.Type != e.Spec.Type {
|
||||||
log.Panicf("bad object from list: %v", el.Items[0])
|
log.Panicf("bad object from list: %v", el.Items[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,10 +384,11 @@ func kubernetesWatchTriggerTests(tprClient *rest.RESTClient) {
|
|||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
// start a watch
|
// start a watch
|
||||||
wi, err := ei.Watch(api.ListOptions{})
|
wi, err := ei.Watch(metav1.ListOptions{})
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
kubernetesWatchTrigger.Metadata.ResourceVersion = ""
|
||||||
e, err = ei.Create(kubernetesWatchTrigger)
|
e, err = ei.Create(kubernetesWatchTrigger)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
defer ei.Delete(e.Metadata.Name, nil)
|
defer ei.Delete(e.Metadata.Name, nil)
|
||||||
@@ -390,9 +401,9 @@ func kubernetesWatchTriggerTests(tprClient *rest.RESTClient) {
|
|||||||
log.Panicf("Didn't get watch event")
|
log.Panicf("Didn't get watch event")
|
||||||
}
|
}
|
||||||
case ev := <-wi.ResultChan():
|
case ev := <-wi.ResultChan():
|
||||||
obj, ok := ev.Object.(*Kuberneteswatchtrigger)
|
obj, ok := ev.Object.(*KubernetesWatchTrigger)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Panicf("Can't cast to Kuberneteswatchtrigger")
|
log.Panicf("Can't cast to KubernetesWatchTrigger")
|
||||||
}
|
}
|
||||||
if obj.Spec.Type != kubernetesWatchTrigger.Spec.Type {
|
if obj.Spec.Type != kubernetesWatchTrigger.Spec.Type {
|
||||||
log.Panicf("Bad object from watch: %#v", obj)
|
log.Panicf("Bad object from watch: %#v", obj)
|
||||||
@@ -403,7 +414,7 @@ func kubernetesWatchTriggerTests(tprClient *rest.RESTClient) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTpr(t *testing.T) {
|
func TestCrd(t *testing.T) {
|
||||||
// skip test if no cluster available for testing
|
// skip test if no cluster available for testing
|
||||||
kubeconfig := os.Getenv("KUBECONFIG")
|
kubeconfig := os.Getenv("KUBECONFIG")
|
||||||
if len(kubeconfig) == 0 {
|
if len(kubeconfig) == 0 {
|
||||||
@@ -413,22 +424,22 @@ func TestTpr(t *testing.T) {
|
|||||||
|
|
||||||
// Create the client config. Needs the KUBECONFIG env var to
|
// Create the client config. Needs the KUBECONFIG env var to
|
||||||
// point at a valid kubeconfig.
|
// point at a valid kubeconfig.
|
||||||
config, clientset, err := GetKubernetesClient()
|
config, _, apiExtClient, err := GetKubernetesClient()
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
// init our types
|
// init our types
|
||||||
err = EnsureFissionTPRs(clientset)
|
err = EnsureFissionCRDs(apiExtClient)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
// rest client with knowledge about our tpr types
|
// rest client with knowledge about our crd types
|
||||||
tprClient, err := GetTprClient(config)
|
crdClient, err := GetCrdClient(config)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
err = waitForTPRs(tprClient)
|
err = waitForCRDs(crdClient)
|
||||||
panicIf(err)
|
panicIf(err)
|
||||||
|
|
||||||
functionTests(tprClient)
|
functionTests(crdClient)
|
||||||
environmentTests(tprClient)
|
environmentTests(crdClient)
|
||||||
httpTriggerTests(tprClient)
|
httpTriggerTests(crdClient)
|
||||||
kubernetesWatchTriggerTests(tprClient)
|
kubernetesWatchTriggerTests(crdClient)
|
||||||
}
|
}
|
||||||
@@ -14,12 +14,13 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package tpr
|
package crd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/client-go/1.5/rest"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -27,9 +28,9 @@ type (
|
|||||||
Create(*Environment) (*Environment, error)
|
Create(*Environment) (*Environment, error)
|
||||||
Get(name string) (*Environment, error)
|
Get(name string) (*Environment, error)
|
||||||
Update(*Environment) (*Environment, error)
|
Update(*Environment) (*Environment, error)
|
||||||
Delete(name string, options *api.DeleteOptions) error
|
Delete(name string, options *metav1.DeleteOptions) error
|
||||||
List(opts api.ListOptions) (*EnvironmentList, error)
|
List(opts metav1.ListOptions) (*EnvironmentList, error)
|
||||||
Watch(opts api.ListOptions) (watch.Interface, error)
|
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
environmentClient struct {
|
environmentClient struct {
|
||||||
@@ -38,9 +39,9 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func MakeEnvironmentInterface(tprClient *rest.RESTClient, namespace string) EnvironmentInterface {
|
func MakeEnvironmentInterface(crdClient *rest.RESTClient, namespace string) EnvironmentInterface {
|
||||||
return &environmentClient{
|
return &environmentClient{
|
||||||
client: tprClient,
|
client: crdClient,
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,7 +86,7 @@ func (ec *environmentClient) Update(e *Environment) (*Environment, error) {
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *environmentClient) Delete(name string, opts *api.DeleteOptions) error {
|
func (ec *environmentClient) Delete(name string, opts *metav1.DeleteOptions) error {
|
||||||
return ec.client.Delete().
|
return ec.client.Delete().
|
||||||
Namespace(ec.namespace).
|
Namespace(ec.namespace).
|
||||||
Resource("environments").
|
Resource("environments").
|
||||||
@@ -95,12 +96,12 @@ func (ec *environmentClient) Delete(name string, opts *api.DeleteOptions) error
|
|||||||
Error()
|
Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *environmentClient) List(opts api.ListOptions) (*EnvironmentList, error) {
|
func (ec *environmentClient) List(opts metav1.ListOptions) (*EnvironmentList, error) {
|
||||||
var result EnvironmentList
|
var result EnvironmentList
|
||||||
err := ec.client.Get().
|
err := ec.client.Get().
|
||||||
Namespace(ec.namespace).
|
Namespace(ec.namespace).
|
||||||
Resource("environments").
|
Resource("environments").
|
||||||
VersionedParams(&opts, api.ParameterCodec).
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
Do().
|
Do().
|
||||||
Into(&result)
|
Into(&result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -109,11 +110,11 @@ func (ec *environmentClient) List(opts api.ListOptions) (*EnvironmentList, error
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *environmentClient) Watch(opts api.ListOptions) (watch.Interface, error) {
|
func (ec *environmentClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||||
return ec.client.Get().
|
return ec.client.Get().
|
||||||
Prefix("watch").
|
Prefix("watch").
|
||||||
Namespace(ec.namespace).
|
Namespace(ec.namespace).
|
||||||
Resource("environments").
|
Resource("environments").
|
||||||
VersionedParams(&opts, api.ParameterCodec).
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
Watch()
|
Watch()
|
||||||
}
|
}
|
||||||
@@ -14,12 +14,13 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package tpr
|
package crd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/client-go/1.5/rest"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -27,9 +28,9 @@ type (
|
|||||||
Create(*Function) (*Function, error)
|
Create(*Function) (*Function, error)
|
||||||
Get(name string) (*Function, error)
|
Get(name string) (*Function, error)
|
||||||
Update(*Function) (*Function, error)
|
Update(*Function) (*Function, error)
|
||||||
Delete(name string, options *api.DeleteOptions) error
|
Delete(name string, options *metav1.DeleteOptions) error
|
||||||
List(opts api.ListOptions) (*FunctionList, error)
|
List(opts metav1.ListOptions) (*FunctionList, error)
|
||||||
Watch(opts api.ListOptions) (watch.Interface, error)
|
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
functionClient struct {
|
functionClient struct {
|
||||||
@@ -38,9 +39,9 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func MakeFunctionInterface(tprClient *rest.RESTClient, namespace string) FunctionInterface {
|
func MakeFunctionInterface(crdClient *rest.RESTClient, namespace string) FunctionInterface {
|
||||||
return &functionClient{
|
return &functionClient{
|
||||||
client: tprClient,
|
client: crdClient,
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,7 +86,7 @@ func (fc *functionClient) Update(f *Function) (*Function, error) {
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *functionClient) Delete(name string, opts *api.DeleteOptions) error {
|
func (fc *functionClient) Delete(name string, opts *metav1.DeleteOptions) error {
|
||||||
return fc.client.Delete().
|
return fc.client.Delete().
|
||||||
Namespace(fc.namespace).
|
Namespace(fc.namespace).
|
||||||
Resource("functions").
|
Resource("functions").
|
||||||
@@ -95,12 +96,12 @@ func (fc *functionClient) Delete(name string, opts *api.DeleteOptions) error {
|
|||||||
Error()
|
Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *functionClient) List(opts api.ListOptions) (*FunctionList, error) {
|
func (fc *functionClient) List(opts metav1.ListOptions) (*FunctionList, error) {
|
||||||
var result FunctionList
|
var result FunctionList
|
||||||
err := fc.client.Get().
|
err := fc.client.Get().
|
||||||
Namespace(fc.namespace).
|
Namespace(fc.namespace).
|
||||||
Resource("functions").
|
Resource("functions").
|
||||||
VersionedParams(&opts, api.ParameterCodec).
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
Do().
|
Do().
|
||||||
Into(&result)
|
Into(&result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -109,11 +110,11 @@ func (fc *functionClient) List(opts api.ListOptions) (*FunctionList, error) {
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *functionClient) Watch(opts api.ListOptions) (watch.Interface, error) {
|
func (fc *functionClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||||
return fc.client.Get().
|
return fc.client.Get().
|
||||||
Prefix("watch").
|
Prefix("watch").
|
||||||
Namespace(fc.namespace).
|
Namespace(fc.namespace).
|
||||||
Resource("functions").
|
Resource("functions").
|
||||||
VersionedParams(&opts, api.ParameterCodec).
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
Watch()
|
Watch()
|
||||||
}
|
}
|
||||||
@@ -14,22 +14,23 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package tpr
|
package crd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/client-go/1.5/rest"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
HttptriggerInterface interface {
|
HTTPTriggerInterface interface {
|
||||||
Create(*Httptrigger) (*Httptrigger, error)
|
Create(*HTTPTrigger) (*HTTPTrigger, error)
|
||||||
Get(name string) (*Httptrigger, error)
|
Get(name string) (*HTTPTrigger, error)
|
||||||
Update(*Httptrigger) (*Httptrigger, error)
|
Update(*HTTPTrigger) (*HTTPTrigger, error)
|
||||||
Delete(name string, options *api.DeleteOptions) error
|
Delete(name string, options *metav1.DeleteOptions) error
|
||||||
List(opts api.ListOptions) (*HttptriggerList, error)
|
List(opts metav1.ListOptions) (*HTTPTriggerList, error)
|
||||||
Watch(opts api.ListOptions) (watch.Interface, error)
|
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
httpTriggerClient struct {
|
httpTriggerClient struct {
|
||||||
@@ -38,15 +39,15 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func MakeHttptriggerInterface(tprClient *rest.RESTClient, namespace string) HttptriggerInterface {
|
func MakeHTTPTriggerInterface(crdClient *rest.RESTClient, namespace string) HTTPTriggerInterface {
|
||||||
return &httpTriggerClient{
|
return &httpTriggerClient{
|
||||||
client: tprClient,
|
client: crdClient,
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpTriggerClient) Create(obj *Httptrigger) (*Httptrigger, error) {
|
func (c *httpTriggerClient) Create(obj *HTTPTrigger) (*HTTPTrigger, error) {
|
||||||
var result Httptrigger
|
var result HTTPTrigger
|
||||||
err := c.client.Post().
|
err := c.client.Post().
|
||||||
Resource("httptriggers").
|
Resource("httptriggers").
|
||||||
Namespace(c.namespace).
|
Namespace(c.namespace).
|
||||||
@@ -58,8 +59,8 @@ func (c *httpTriggerClient) Create(obj *Httptrigger) (*Httptrigger, error) {
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpTriggerClient) Get(name string) (*Httptrigger, error) {
|
func (c *httpTriggerClient) Get(name string) (*HTTPTrigger, error) {
|
||||||
var result Httptrigger
|
var result HTTPTrigger
|
||||||
err := c.client.Get().
|
err := c.client.Get().
|
||||||
Resource("httptriggers").
|
Resource("httptriggers").
|
||||||
Namespace(c.namespace).
|
Namespace(c.namespace).
|
||||||
@@ -71,8 +72,8 @@ func (c *httpTriggerClient) Get(name string) (*Httptrigger, error) {
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpTriggerClient) Update(obj *Httptrigger) (*Httptrigger, error) {
|
func (c *httpTriggerClient) Update(obj *HTTPTrigger) (*HTTPTrigger, error) {
|
||||||
var result Httptrigger
|
var result HTTPTrigger
|
||||||
err := c.client.Put().
|
err := c.client.Put().
|
||||||
Resource("httptriggers").
|
Resource("httptriggers").
|
||||||
Namespace(c.namespace).
|
Namespace(c.namespace).
|
||||||
@@ -85,7 +86,7 @@ func (c *httpTriggerClient) Update(obj *Httptrigger) (*Httptrigger, error) {
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpTriggerClient) Delete(name string, opts *api.DeleteOptions) error {
|
func (c *httpTriggerClient) Delete(name string, opts *metav1.DeleteOptions) error {
|
||||||
return c.client.Delete().
|
return c.client.Delete().
|
||||||
Namespace(c.namespace).
|
Namespace(c.namespace).
|
||||||
Resource("httptriggers").
|
Resource("httptriggers").
|
||||||
@@ -95,12 +96,12 @@ func (c *httpTriggerClient) Delete(name string, opts *api.DeleteOptions) error {
|
|||||||
Error()
|
Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpTriggerClient) List(opts api.ListOptions) (*HttptriggerList, error) {
|
func (c *httpTriggerClient) List(opts metav1.ListOptions) (*HTTPTriggerList, error) {
|
||||||
var result HttptriggerList
|
var result HTTPTriggerList
|
||||||
err := c.client.Get().
|
err := c.client.Get().
|
||||||
Namespace(c.namespace).
|
Namespace(c.namespace).
|
||||||
Resource("httptriggers").
|
Resource("httptriggers").
|
||||||
VersionedParams(&opts, api.ParameterCodec).
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
Do().
|
Do().
|
||||||
Into(&result)
|
Into(&result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -109,11 +110,11 @@ func (c *httpTriggerClient) List(opts api.ListOptions) (*HttptriggerList, error)
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpTriggerClient) Watch(opts api.ListOptions) (watch.Interface, error) {
|
func (c *httpTriggerClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||||
return c.client.Get().
|
return c.client.Get().
|
||||||
Prefix("watch").
|
Prefix("watch").
|
||||||
Namespace(c.namespace).
|
Namespace(c.namespace).
|
||||||
Resource("httptriggers").
|
Resource("httptriggers").
|
||||||
VersionedParams(&opts, api.ParameterCodec).
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
Watch()
|
Watch()
|
||||||
}
|
}
|
||||||
@@ -14,12 +14,12 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package tpr
|
package crd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Given metadata, create a key that uniquely identifies the contents
|
// Given metadata, create a key that uniquely identifies the contents
|
||||||
@@ -28,6 +28,6 @@ import (
|
|||||||
// content. (ResourceVersion may also update on status updates, so
|
// content. (ResourceVersion may also update on status updates, so
|
||||||
// this will result in some unnecessary cache misses. That should be
|
// this will result in some unnecessary cache misses. That should be
|
||||||
// ok.)
|
// ok.)
|
||||||
func CacheKey(metadata *api.ObjectMeta) string {
|
func CacheKey(metadata *metav1.ObjectMeta) string {
|
||||||
return fmt.Sprintf("%v_%v", metadata.UID, metadata.ResourceVersion)
|
return fmt.Sprintf("%v_%v", metadata.UID, metadata.ResourceVersion)
|
||||||
}
|
}
|
||||||
@@ -14,22 +14,23 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package tpr
|
package crd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/client-go/1.5/rest"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
KuberneteswatchtriggerInterface interface {
|
KubernetesWatchTriggerInterface interface {
|
||||||
Create(*Kuberneteswatchtrigger) (*Kuberneteswatchtrigger, error)
|
Create(*KubernetesWatchTrigger) (*KubernetesWatchTrigger, error)
|
||||||
Get(name string) (*Kuberneteswatchtrigger, error)
|
Get(name string) (*KubernetesWatchTrigger, error)
|
||||||
Update(*Kuberneteswatchtrigger) (*Kuberneteswatchtrigger, error)
|
Update(*KubernetesWatchTrigger) (*KubernetesWatchTrigger, error)
|
||||||
Delete(name string, options *api.DeleteOptions) error
|
Delete(name string, options *metav1.DeleteOptions) error
|
||||||
List(opts api.ListOptions) (*KuberneteswatchtriggerList, error)
|
List(opts metav1.ListOptions) (*KubernetesWatchTriggerList, error)
|
||||||
Watch(opts api.ListOptions) (watch.Interface, error)
|
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
kubernetesWatchTriggerClient struct {
|
kubernetesWatchTriggerClient struct {
|
||||||
@@ -38,15 +39,15 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func MakeKuberneteswatchtriggerInterface(tprClient *rest.RESTClient, namespace string) KuberneteswatchtriggerInterface {
|
func MakeKubernetesWatchTriggerInterface(crdClient *rest.RESTClient, namespace string) KubernetesWatchTriggerInterface {
|
||||||
return &kubernetesWatchTriggerClient{
|
return &kubernetesWatchTriggerClient{
|
||||||
client: tprClient,
|
client: crdClient,
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *kubernetesWatchTriggerClient) Create(obj *Kuberneteswatchtrigger) (*Kuberneteswatchtrigger, error) {
|
func (c *kubernetesWatchTriggerClient) Create(obj *KubernetesWatchTrigger) (*KubernetesWatchTrigger, error) {
|
||||||
var result Kuberneteswatchtrigger
|
var result KubernetesWatchTrigger
|
||||||
err := c.client.Post().
|
err := c.client.Post().
|
||||||
Resource("kuberneteswatchtriggers").
|
Resource("kuberneteswatchtriggers").
|
||||||
Namespace(c.namespace).
|
Namespace(c.namespace).
|
||||||
@@ -58,8 +59,8 @@ func (c *kubernetesWatchTriggerClient) Create(obj *Kuberneteswatchtrigger) (*Kub
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *kubernetesWatchTriggerClient) Get(name string) (*Kuberneteswatchtrigger, error) {
|
func (c *kubernetesWatchTriggerClient) Get(name string) (*KubernetesWatchTrigger, error) {
|
||||||
var result Kuberneteswatchtrigger
|
var result KubernetesWatchTrigger
|
||||||
err := c.client.Get().
|
err := c.client.Get().
|
||||||
Resource("kuberneteswatchtriggers").
|
Resource("kuberneteswatchtriggers").
|
||||||
Namespace(c.namespace).
|
Namespace(c.namespace).
|
||||||
@@ -71,8 +72,8 @@ func (c *kubernetesWatchTriggerClient) Get(name string) (*Kuberneteswatchtrigger
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *kubernetesWatchTriggerClient) Update(obj *Kuberneteswatchtrigger) (*Kuberneteswatchtrigger, error) {
|
func (c *kubernetesWatchTriggerClient) Update(obj *KubernetesWatchTrigger) (*KubernetesWatchTrigger, error) {
|
||||||
var result Kuberneteswatchtrigger
|
var result KubernetesWatchTrigger
|
||||||
err := c.client.Put().
|
err := c.client.Put().
|
||||||
Resource("kuberneteswatchtriggers").
|
Resource("kuberneteswatchtriggers").
|
||||||
Namespace(c.namespace).
|
Namespace(c.namespace).
|
||||||
@@ -85,7 +86,7 @@ func (c *kubernetesWatchTriggerClient) Update(obj *Kuberneteswatchtrigger) (*Kub
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *kubernetesWatchTriggerClient) Delete(name string, opts *api.DeleteOptions) error {
|
func (c *kubernetesWatchTriggerClient) Delete(name string, opts *metav1.DeleteOptions) error {
|
||||||
return c.client.Delete().
|
return c.client.Delete().
|
||||||
Namespace(c.namespace).
|
Namespace(c.namespace).
|
||||||
Resource("kuberneteswatchtriggers").
|
Resource("kuberneteswatchtriggers").
|
||||||
@@ -95,12 +96,12 @@ func (c *kubernetesWatchTriggerClient) Delete(name string, opts *api.DeleteOptio
|
|||||||
Error()
|
Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *kubernetesWatchTriggerClient) List(opts api.ListOptions) (*KuberneteswatchtriggerList, error) {
|
func (c *kubernetesWatchTriggerClient) List(opts metav1.ListOptions) (*KubernetesWatchTriggerList, error) {
|
||||||
var result KuberneteswatchtriggerList
|
var result KubernetesWatchTriggerList
|
||||||
err := c.client.Get().
|
err := c.client.Get().
|
||||||
Namespace(c.namespace).
|
Namespace(c.namespace).
|
||||||
Resource("kuberneteswatchtriggers").
|
Resource("kuberneteswatchtriggers").
|
||||||
VersionedParams(&opts, api.ParameterCodec).
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
Do().
|
Do().
|
||||||
Into(&result)
|
Into(&result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -109,11 +110,11 @@ func (c *kubernetesWatchTriggerClient) List(opts api.ListOptions) (*Kuberneteswa
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *kubernetesWatchTriggerClient) Watch(opts api.ListOptions) (watch.Interface, error) {
|
func (c *kubernetesWatchTriggerClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||||
return c.client.Get().
|
return c.client.Get().
|
||||||
Prefix("watch").
|
Prefix("watch").
|
||||||
Namespace(c.namespace).
|
Namespace(c.namespace).
|
||||||
Resource("kuberneteswatchtriggers").
|
Resource("kuberneteswatchtriggers").
|
||||||
VersionedParams(&opts, api.ParameterCodec).
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
Watch()
|
Watch()
|
||||||
}
|
}
|
||||||
@@ -14,39 +14,40 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package tpr
|
package crd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/client-go/1.5/rest"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
MessagequeuetriggerInterface interface {
|
MessageQueueTriggerInterface interface {
|
||||||
Create(*Messagequeuetrigger) (*Messagequeuetrigger, error)
|
Create(*MessageQueueTrigger) (*MessageQueueTrigger, error)
|
||||||
Get(name string) (*Messagequeuetrigger, error)
|
Get(name string) (*MessageQueueTrigger, error)
|
||||||
Update(*Messagequeuetrigger) (*Messagequeuetrigger, error)
|
Update(*MessageQueueTrigger) (*MessageQueueTrigger, error)
|
||||||
Delete(name string, options *api.DeleteOptions) error
|
Delete(name string, options *metav1.DeleteOptions) error
|
||||||
List(opts api.ListOptions) (*MessagequeuetriggerList, error)
|
List(opts metav1.ListOptions) (*MessageQueueTriggerList, error)
|
||||||
Watch(opts api.ListOptions) (watch.Interface, error)
|
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
messagequeuetriggerClient struct {
|
messageQueueTriggerClient struct {
|
||||||
client *rest.RESTClient
|
client *rest.RESTClient
|
||||||
namespace string
|
namespace string
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func MakeMessagequeuetriggerInterface(tprClient *rest.RESTClient, namespace string) MessagequeuetriggerInterface {
|
func MakeMessageQueueTriggerInterface(crdClient *rest.RESTClient, namespace string) MessageQueueTriggerInterface {
|
||||||
return &messagequeuetriggerClient{
|
return &messageQueueTriggerClient{
|
||||||
client: tprClient,
|
client: crdClient,
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *messagequeuetriggerClient) Create(f *Messagequeuetrigger) (*Messagequeuetrigger, error) {
|
func (fc *messageQueueTriggerClient) Create(f *MessageQueueTrigger) (*MessageQueueTrigger, error) {
|
||||||
var result Messagequeuetrigger
|
var result MessageQueueTrigger
|
||||||
err := fc.client.Post().
|
err := fc.client.Post().
|
||||||
Resource("messagequeuetriggers").
|
Resource("messagequeuetriggers").
|
||||||
Namespace(fc.namespace).
|
Namespace(fc.namespace).
|
||||||
@@ -58,8 +59,8 @@ func (fc *messagequeuetriggerClient) Create(f *Messagequeuetrigger) (*Messageque
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *messagequeuetriggerClient) Get(name string) (*Messagequeuetrigger, error) {
|
func (fc *messageQueueTriggerClient) Get(name string) (*MessageQueueTrigger, error) {
|
||||||
var result Messagequeuetrigger
|
var result MessageQueueTrigger
|
||||||
err := fc.client.Get().
|
err := fc.client.Get().
|
||||||
Resource("messagequeuetriggers").
|
Resource("messagequeuetriggers").
|
||||||
Namespace(fc.namespace).
|
Namespace(fc.namespace).
|
||||||
@@ -71,8 +72,8 @@ func (fc *messagequeuetriggerClient) Get(name string) (*Messagequeuetrigger, err
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *messagequeuetriggerClient) Update(f *Messagequeuetrigger) (*Messagequeuetrigger, error) {
|
func (fc *messageQueueTriggerClient) Update(f *MessageQueueTrigger) (*MessageQueueTrigger, error) {
|
||||||
var result Messagequeuetrigger
|
var result MessageQueueTrigger
|
||||||
err := fc.client.Put().
|
err := fc.client.Put().
|
||||||
Resource("messagequeuetriggers").
|
Resource("messagequeuetriggers").
|
||||||
Namespace(fc.namespace).
|
Namespace(fc.namespace).
|
||||||
@@ -85,7 +86,7 @@ func (fc *messagequeuetriggerClient) Update(f *Messagequeuetrigger) (*Messageque
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *messagequeuetriggerClient) Delete(name string, opts *api.DeleteOptions) error {
|
func (fc *messageQueueTriggerClient) Delete(name string, opts *metav1.DeleteOptions) error {
|
||||||
return fc.client.Delete().
|
return fc.client.Delete().
|
||||||
Namespace(fc.namespace).
|
Namespace(fc.namespace).
|
||||||
Resource("messagequeuetriggers").
|
Resource("messagequeuetriggers").
|
||||||
@@ -95,12 +96,12 @@ func (fc *messagequeuetriggerClient) Delete(name string, opts *api.DeleteOptions
|
|||||||
Error()
|
Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *messagequeuetriggerClient) List(opts api.ListOptions) (*MessagequeuetriggerList, error) {
|
func (fc *messageQueueTriggerClient) List(opts metav1.ListOptions) (*MessageQueueTriggerList, error) {
|
||||||
var result MessagequeuetriggerList
|
var result MessageQueueTriggerList
|
||||||
err := fc.client.Get().
|
err := fc.client.Get().
|
||||||
Namespace(fc.namespace).
|
Namespace(fc.namespace).
|
||||||
Resource("messagequeuetriggers").
|
Resource("messagequeuetriggers").
|
||||||
VersionedParams(&opts, api.ParameterCodec).
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
Do().
|
Do().
|
||||||
Into(&result)
|
Into(&result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -109,11 +110,11 @@ func (fc *messagequeuetriggerClient) List(opts api.ListOptions) (*Messagequeuetr
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *messagequeuetriggerClient) Watch(opts api.ListOptions) (watch.Interface, error) {
|
func (fc *messageQueueTriggerClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||||
return fc.client.Get().
|
return fc.client.Get().
|
||||||
Prefix("watch").
|
Prefix("watch").
|
||||||
Namespace(fc.namespace).
|
Namespace(fc.namespace).
|
||||||
Resource("messagequeuetriggers").
|
Resource("messagequeuetriggers").
|
||||||
VersionedParams(&opts, api.ParameterCodec).
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
Watch()
|
Watch()
|
||||||
}
|
}
|
||||||
@@ -14,12 +14,13 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package tpr
|
package crd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/client-go/1.5/rest"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -27,9 +28,9 @@ type (
|
|||||||
Create(*Package) (*Package, error)
|
Create(*Package) (*Package, error)
|
||||||
Get(name string) (*Package, error)
|
Get(name string) (*Package, error)
|
||||||
Update(*Package) (*Package, error)
|
Update(*Package) (*Package, error)
|
||||||
Delete(name string, options *api.DeleteOptions) error
|
Delete(name string, options *metav1.DeleteOptions) error
|
||||||
List(opts api.ListOptions) (*PackageList, error)
|
List(opts metav1.ListOptions) (*PackageList, error)
|
||||||
Watch(opts api.ListOptions) (watch.Interface, error)
|
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
packageClient struct {
|
packageClient struct {
|
||||||
@@ -38,9 +39,9 @@ type (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func MakePackageInterface(tprClient *rest.RESTClient, namespace string) PackageInterface {
|
func MakePackageInterface(crdClient *rest.RESTClient, namespace string) PackageInterface {
|
||||||
return &packageClient{
|
return &packageClient{
|
||||||
client: tprClient,
|
client: crdClient,
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,7 +86,7 @@ func (c *packageClient) Update(f *Package) (*Package, error) {
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *packageClient) Delete(name string, opts *api.DeleteOptions) error {
|
func (c *packageClient) Delete(name string, opts *metav1.DeleteOptions) error {
|
||||||
return c.client.Delete().
|
return c.client.Delete().
|
||||||
Namespace(c.namespace).
|
Namespace(c.namespace).
|
||||||
Resource("packages").
|
Resource("packages").
|
||||||
@@ -95,12 +96,12 @@ func (c *packageClient) Delete(name string, opts *api.DeleteOptions) error {
|
|||||||
Error()
|
Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *packageClient) List(opts api.ListOptions) (*PackageList, error) {
|
func (c *packageClient) List(opts metav1.ListOptions) (*PackageList, error) {
|
||||||
var result PackageList
|
var result PackageList
|
||||||
err := c.client.Get().
|
err := c.client.Get().
|
||||||
Namespace(c.namespace).
|
Namespace(c.namespace).
|
||||||
Resource("packages").
|
Resource("packages").
|
||||||
VersionedParams(&opts, api.ParameterCodec).
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
Do().
|
Do().
|
||||||
Into(&result)
|
Into(&result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -109,11 +110,11 @@ func (c *packageClient) List(opts api.ListOptions) (*PackageList, error) {
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *packageClient) Watch(opts api.ListOptions) (watch.Interface, error) {
|
func (c *packageClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||||
return c.client.Get().
|
return c.client.Get().
|
||||||
Prefix("watch").
|
Prefix("watch").
|
||||||
Namespace(c.namespace).
|
Namespace(c.namespace).
|
||||||
Resource("packages").
|
Resource("packages").
|
||||||
VersionedParams(&opts, api.ParameterCodec).
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
Watch()
|
Watch()
|
||||||
}
|
}
|
||||||
@@ -14,39 +14,40 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package tpr
|
package crd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/client-go/1.5/rest"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
TimetriggerInterface interface {
|
TimeTriggerInterface interface {
|
||||||
Create(*Timetrigger) (*Timetrigger, error)
|
Create(*TimeTrigger) (*TimeTrigger, error)
|
||||||
Get(name string) (*Timetrigger, error)
|
Get(name string) (*TimeTrigger, error)
|
||||||
Update(*Timetrigger) (*Timetrigger, error)
|
Update(*TimeTrigger) (*TimeTrigger, error)
|
||||||
Delete(name string, options *api.DeleteOptions) error
|
Delete(name string, options *metav1.DeleteOptions) error
|
||||||
List(opts api.ListOptions) (*TimetriggerList, error)
|
List(opts metav1.ListOptions) (*TimeTriggerList, error)
|
||||||
Watch(opts api.ListOptions) (watch.Interface, error)
|
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
timetriggerClient struct {
|
timeTriggerClient struct {
|
||||||
client *rest.RESTClient
|
client *rest.RESTClient
|
||||||
namespace string
|
namespace string
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func MakeTimetriggerInterface(tprClient *rest.RESTClient, namespace string) TimetriggerInterface {
|
func MakeTimeTriggerInterface(crdClient *rest.RESTClient, namespace string) TimeTriggerInterface {
|
||||||
return &timetriggerClient{
|
return &timeTriggerClient{
|
||||||
client: tprClient,
|
client: crdClient,
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *timetriggerClient) Create(f *Timetrigger) (*Timetrigger, error) {
|
func (fc *timeTriggerClient) Create(f *TimeTrigger) (*TimeTrigger, error) {
|
||||||
var result Timetrigger
|
var result TimeTrigger
|
||||||
err := fc.client.Post().
|
err := fc.client.Post().
|
||||||
Resource("timetriggers").
|
Resource("timetriggers").
|
||||||
Namespace(fc.namespace).
|
Namespace(fc.namespace).
|
||||||
@@ -58,8 +59,8 @@ func (fc *timetriggerClient) Create(f *Timetrigger) (*Timetrigger, error) {
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *timetriggerClient) Get(name string) (*Timetrigger, error) {
|
func (fc *timeTriggerClient) Get(name string) (*TimeTrigger, error) {
|
||||||
var result Timetrigger
|
var result TimeTrigger
|
||||||
err := fc.client.Get().
|
err := fc.client.Get().
|
||||||
Resource("timetriggers").
|
Resource("timetriggers").
|
||||||
Namespace(fc.namespace).
|
Namespace(fc.namespace).
|
||||||
@@ -71,8 +72,8 @@ func (fc *timetriggerClient) Get(name string) (*Timetrigger, error) {
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *timetriggerClient) Update(f *Timetrigger) (*Timetrigger, error) {
|
func (fc *timeTriggerClient) Update(f *TimeTrigger) (*TimeTrigger, error) {
|
||||||
var result Timetrigger
|
var result TimeTrigger
|
||||||
err := fc.client.Put().
|
err := fc.client.Put().
|
||||||
Resource("timetriggers").
|
Resource("timetriggers").
|
||||||
Namespace(fc.namespace).
|
Namespace(fc.namespace).
|
||||||
@@ -85,7 +86,7 @@ func (fc *timetriggerClient) Update(f *Timetrigger) (*Timetrigger, error) {
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *timetriggerClient) Delete(name string, opts *api.DeleteOptions) error {
|
func (fc *timeTriggerClient) Delete(name string, opts *metav1.DeleteOptions) error {
|
||||||
return fc.client.Delete().
|
return fc.client.Delete().
|
||||||
Namespace(fc.namespace).
|
Namespace(fc.namespace).
|
||||||
Resource("timetriggers").
|
Resource("timetriggers").
|
||||||
@@ -95,12 +96,12 @@ func (fc *timetriggerClient) Delete(name string, opts *api.DeleteOptions) error
|
|||||||
Error()
|
Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *timetriggerClient) List(opts api.ListOptions) (*TimetriggerList, error) {
|
func (fc *timeTriggerClient) List(opts metav1.ListOptions) (*TimeTriggerList, error) {
|
||||||
var result TimetriggerList
|
var result TimeTriggerList
|
||||||
err := fc.client.Get().
|
err := fc.client.Get().
|
||||||
Namespace(fc.namespace).
|
Namespace(fc.namespace).
|
||||||
Resource("timetriggers").
|
Resource("timetriggers").
|
||||||
VersionedParams(&opts, api.ParameterCodec).
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
Do().
|
Do().
|
||||||
Into(&result)
|
Into(&result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -109,11 +110,11 @@ func (fc *timetriggerClient) List(opts api.ListOptions) (*TimetriggerList, error
|
|||||||
return &result, nil
|
return &result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *timetriggerClient) Watch(opts api.ListOptions) (watch.Interface, error) {
|
func (fc *timeTriggerClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||||
return fc.client.Get().
|
return fc.client.Get().
|
||||||
Prefix("watch").
|
Prefix("watch").
|
||||||
Namespace(fc.namespace).
|
Namespace(fc.namespace).
|
||||||
Resource("timetriggers").
|
Resource("timetriggers").
|
||||||
VersionedParams(&opts, api.ParameterCodec).
|
VersionedParams(&opts, scheme.ParameterCodec).
|
||||||
Watch()
|
Watch()
|
||||||
}
|
}
|
||||||
+228
@@ -0,0 +1,228 @@
|
|||||||
|
/*
|
||||||
|
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 crd
|
||||||
|
|
||||||
|
import (
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
|
||||||
|
"github.com/fission/fission"
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
// To add a Fission CRD type:
|
||||||
|
// 1. Create a "spec" type, for everything in the type except metadata
|
||||||
|
// 2. Create the type with metadata + the spec
|
||||||
|
// 3. Create a list type (for example see FunctionList and Function, below)
|
||||||
|
// 4. Add methods at the bottom of this file for satisfying Object and List interfaces
|
||||||
|
// 5. Add the type to configureClient in client.go
|
||||||
|
// 6. Add the type to EnsureFissionCRDs in crd.go
|
||||||
|
// 7. Add tests to crd_test.go
|
||||||
|
// 8. Add a CRUD Interface type (analogous to FunctionInterface in function.go)
|
||||||
|
// 9. Add a getter method for your interface type to FissionClient in client.go
|
||||||
|
//
|
||||||
|
|
||||||
|
type (
|
||||||
|
// Packages. Think of these as function-level images.
|
||||||
|
Package struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
Metadata metav1.ObjectMeta `json:"metadata"`
|
||||||
|
Spec fission.PackageSpec `json:"spec"`
|
||||||
|
|
||||||
|
Status fission.PackageStatus `json:"status"`
|
||||||
|
}
|
||||||
|
PackageList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
Metadata metav1.ListMeta `json:"metadata"`
|
||||||
|
|
||||||
|
Items []Package `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions.
|
||||||
|
Function struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
Metadata metav1.ObjectMeta `json:"metadata"`
|
||||||
|
Spec fission.FunctionSpec `json:"spec"`
|
||||||
|
}
|
||||||
|
FunctionList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
Metadata metav1.ListMeta `json:"metadata"`
|
||||||
|
|
||||||
|
Items []Function `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Environments.
|
||||||
|
Environment struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
Metadata metav1.ObjectMeta `json:"metadata"`
|
||||||
|
Spec fission.EnvironmentSpec `json:"spec"`
|
||||||
|
}
|
||||||
|
EnvironmentList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
Metadata metav1.ListMeta `json:"metadata"`
|
||||||
|
|
||||||
|
Items []Environment `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTPTrigger struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
Metadata metav1.ObjectMeta `json:"metadata"`
|
||||||
|
Spec fission.HTTPTriggerSpec `json:"spec"`
|
||||||
|
}
|
||||||
|
HTTPTriggerList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
Metadata metav1.ListMeta `json:"metadata"`
|
||||||
|
|
||||||
|
Items []HTTPTrigger `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kubernetes Watches as triggers
|
||||||
|
KubernetesWatchTrigger struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
Metadata metav1.ObjectMeta `json:"metadata"`
|
||||||
|
Spec fission.KubernetesWatchTriggerSpec `json:"spec"`
|
||||||
|
}
|
||||||
|
KubernetesWatchTriggerList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
Metadata metav1.ListMeta `json:"metadata"`
|
||||||
|
|
||||||
|
Items []KubernetesWatchTrigger `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time triggers
|
||||||
|
TimeTrigger struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
Metadata metav1.ObjectMeta `json:"metadata"`
|
||||||
|
Spec fission.TimeTriggerSpec `json:"spec"`
|
||||||
|
}
|
||||||
|
TimeTriggerList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
Metadata metav1.ListMeta `json:"metadata"`
|
||||||
|
|
||||||
|
Items []TimeTrigger `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Message Queue triggers
|
||||||
|
MessageQueueTrigger struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
Metadata metav1.ObjectMeta `json:"metadata"`
|
||||||
|
Spec fission.MessageQueueTriggerSpec `json:"spec"`
|
||||||
|
}
|
||||||
|
MessageQueueTriggerList struct {
|
||||||
|
metav1.TypeMeta `json:",inline"`
|
||||||
|
Metadata metav1.ListMeta `json:"metadata"`
|
||||||
|
|
||||||
|
Items []MessageQueueTrigger `json:"items"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Each CRD type needs:
|
||||||
|
// GetObjectKind (to satisfy the Object interface)
|
||||||
|
//
|
||||||
|
// In addition, each singular CRD type needs:
|
||||||
|
// GetObjectMeta (to satisfy the ObjectMetaAccessor interface)
|
||||||
|
//
|
||||||
|
// And each list CRD type needs:
|
||||||
|
// GetListMeta (to satisfy the ListMetaAccessor interface)
|
||||||
|
|
||||||
|
func (f *Function) GetObjectKind() schema.ObjectKind {
|
||||||
|
return &f.TypeMeta
|
||||||
|
}
|
||||||
|
func (e *Environment) GetObjectKind() schema.ObjectKind {
|
||||||
|
return &e.TypeMeta
|
||||||
|
}
|
||||||
|
func (ht *HTTPTrigger) GetObjectKind() schema.ObjectKind {
|
||||||
|
return &ht.TypeMeta
|
||||||
|
}
|
||||||
|
func (w *KubernetesWatchTrigger) GetObjectKind() schema.ObjectKind {
|
||||||
|
return &w.TypeMeta
|
||||||
|
}
|
||||||
|
func (w *TimeTrigger) GetObjectKind() schema.ObjectKind {
|
||||||
|
return &w.TypeMeta
|
||||||
|
}
|
||||||
|
func (w *MessageQueueTrigger) GetObjectKind() schema.ObjectKind {
|
||||||
|
return &w.TypeMeta
|
||||||
|
}
|
||||||
|
func (w *Package) GetObjectKind() schema.ObjectKind {
|
||||||
|
return &w.TypeMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Function) GetObjectMeta() metav1.Object {
|
||||||
|
return &f.Metadata
|
||||||
|
}
|
||||||
|
func (e *Environment) GetObjectMeta() metav1.Object {
|
||||||
|
return &e.Metadata
|
||||||
|
}
|
||||||
|
func (ht *HTTPTrigger) GetObjectMeta() metav1.Object {
|
||||||
|
return &ht.Metadata
|
||||||
|
}
|
||||||
|
func (w *KubernetesWatchTrigger) GetObjectMeta() metav1.Object {
|
||||||
|
return &w.Metadata
|
||||||
|
}
|
||||||
|
func (w *TimeTrigger) GetObjectMeta() metav1.Object {
|
||||||
|
return &w.Metadata
|
||||||
|
}
|
||||||
|
func (w *MessageQueueTrigger) GetObjectMeta() metav1.Object {
|
||||||
|
return &w.Metadata
|
||||||
|
}
|
||||||
|
func (w *Package) GetObjectMeta() metav1.Object {
|
||||||
|
return &w.Metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fl *FunctionList) GetObjectKind() schema.ObjectKind {
|
||||||
|
return &fl.TypeMeta
|
||||||
|
}
|
||||||
|
func (el *EnvironmentList) GetObjectKind() schema.ObjectKind {
|
||||||
|
return &el.TypeMeta
|
||||||
|
}
|
||||||
|
func (hl *HTTPTriggerList) GetObjectKind() schema.ObjectKind {
|
||||||
|
return &hl.TypeMeta
|
||||||
|
}
|
||||||
|
func (wl *KubernetesWatchTriggerList) GetObjectKind() schema.ObjectKind {
|
||||||
|
return &wl.TypeMeta
|
||||||
|
}
|
||||||
|
func (wl *TimeTriggerList) GetObjectKind() schema.ObjectKind {
|
||||||
|
return &wl.TypeMeta
|
||||||
|
}
|
||||||
|
func (wl *MessageQueueTriggerList) GetObjectKind() schema.ObjectKind {
|
||||||
|
return &wl.TypeMeta
|
||||||
|
}
|
||||||
|
func (wl *PackageList) GetObjectKind() schema.ObjectKind {
|
||||||
|
return &wl.TypeMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fl *FunctionList) GetListMeta() metav1.List {
|
||||||
|
return &fl.Metadata
|
||||||
|
}
|
||||||
|
func (el *EnvironmentList) GetListMeta() metav1.List {
|
||||||
|
return &el.Metadata
|
||||||
|
}
|
||||||
|
func (hl *HTTPTriggerList) GetListMeta() metav1.List {
|
||||||
|
return &hl.Metadata
|
||||||
|
}
|
||||||
|
func (wl *KubernetesWatchTriggerList) GetListMeta() metav1.List {
|
||||||
|
return &wl.Metadata
|
||||||
|
}
|
||||||
|
func (wl *TimeTriggerList) GetListMeta() metav1.List {
|
||||||
|
return &wl.Metadata
|
||||||
|
}
|
||||||
|
func (wl *MessageQueueTriggerList) GetListMeta() metav1.List {
|
||||||
|
return &wl.Metadata
|
||||||
|
}
|
||||||
|
func (wl *PackageList) GetListMeta() metav1.List {
|
||||||
|
return &wl.Metadata
|
||||||
|
}
|
||||||
+2
-22
@@ -37,10 +37,6 @@ function maybe_first_prompt() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# After a `run` this variable will hold the stdout of the command that was run.
|
|
||||||
# If the command was interactive, this will likely be garbage.
|
|
||||||
#DEMO_RUN_STDOUT=""
|
|
||||||
|
|
||||||
function run() {
|
function run() {
|
||||||
maybe_first_prompt
|
maybe_first_prompt
|
||||||
rate=25
|
rate=25
|
||||||
@@ -52,27 +48,11 @@ function run() {
|
|||||||
sleep 0.5
|
sleep 0.5
|
||||||
fi
|
fi
|
||||||
$1
|
$1
|
||||||
echo; echo -n ">"
|
echo
|
||||||
|
echo -n ">"
|
||||||
read -s
|
read -s
|
||||||
echo -e "\b "
|
echo -e "\b "
|
||||||
# OFILE="$(mktemp -t $(basename $0).XXXXXX)"
|
|
||||||
# script -q -t0 "$OFILE" $1 # [removed -e,-c options -soam]
|
|
||||||
# r=$?
|
|
||||||
# read -d '' -t "${timeout}" -n 10000 # clear stdin
|
|
||||||
# prompt
|
|
||||||
# if [ -z "$DEMO_AUTO_RUN" ]; then
|
|
||||||
# read -s
|
|
||||||
# fi
|
|
||||||
# DEMO_RUN_STDOUT="$(tail -n +2 $OFILE | sed 's/\r//g')"
|
|
||||||
# return $r
|
|
||||||
}
|
|
||||||
|
|
||||||
function relative() {
|
|
||||||
for arg; do
|
|
||||||
echo "$(realpath $(dirname $(which $0)))/$arg" | sed "s|$(realpath $(pwd))|.|"
|
|
||||||
done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SSH_NODE=$(kubectl get nodes | tail -1 | cut -f1 -d' ')
|
SSH_NODE=$(kubectl get nodes | tail -1 | cut -f1 -d' ')
|
||||||
|
|
||||||
#trap "echo" EXIT
|
|
||||||
|
|||||||
@@ -5,12 +5,13 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
//"time"
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/environments/fetcher"
|
"github.com/fission/fission/environments/fetcher"
|
||||||
//"github.com/fission/fission/router"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@@ -31,21 +32,35 @@ func (c *Client) Fetch(fr *fetcher.FetchRequest) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// client := http.Client{
|
maxRetries := 20
|
||||||
// Transport: router.MakeRetryingRoundTripper(10, 50*time.Millisecond),
|
var resp *http.Response
|
||||||
// }
|
|
||||||
|
|
||||||
resp, err := http.Post(c.url, "application/json", bytes.NewReader(body))
|
for i := 0; i < maxRetries; i++ {
|
||||||
if err != nil {
|
resp, err = http.Post(c.url, "application/json", bytes.NewReader(body))
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
if err == nil && resp.StatusCode == 200 {
|
||||||
return fission.MakeErrorFromHTTP(resp)
|
defer resp.Body.Close()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only retry for the specific case of a connection error.
|
||||||
|
if urlErr, ok := err.(*url.Error); ok {
|
||||||
|
if netErr, ok := urlErr.Err.(*net.OpError); ok {
|
||||||
|
if netErr.Op == "dial" {
|
||||||
|
if i < maxRetries-1 {
|
||||||
|
time.Sleep(50 * time.Duration(2*i) * time.Millisecond)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
if err == nil {
|
||||||
|
err = fission.MakeErrorFromHTTP(resp)
|
||||||
|
}
|
||||||
|
log.Printf("Failed to fetch: %v", err)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Upload(fr *fetcher.UploadRequest) (*fetcher.UploadResponse, error) {
|
func (c *Client) Upload(fr *fetcher.UploadRequest) (*fetcher.UploadResponse, error) {
|
||||||
@@ -68,13 +83,11 @@ func (c *Client) Upload(fr *fetcher.UploadRequest) (*fetcher.UploadResponse, err
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Received upload response: %v", string(rBody))
|
uploadResp := fetcher.UploadResponse{}
|
||||||
|
err = json.Unmarshal([]byte(rBody), &uploadResp)
|
||||||
uploadReq := fetcher.UploadResponse{}
|
|
||||||
err = json.Unmarshal([]byte(rBody), &uploadReq)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &uploadReq, nil
|
return &uploadResp, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,23 +16,22 @@ import (
|
|||||||
|
|
||||||
"github.com/mholt/archiver"
|
"github.com/mholt/archiver"
|
||||||
"github.com/satori/go.uuid"
|
"github.com/satori/go.uuid"
|
||||||
"k8s.io/client-go/1.5/kubernetes"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
|
"github.com/fission/fission/crd"
|
||||||
storageSvcClient "github.com/fission/fission/storagesvc/client"
|
storageSvcClient "github.com/fission/fission/storagesvc/client"
|
||||||
"github.com/fission/fission/tpr"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
FetchRequestType int
|
FetchRequestType int
|
||||||
|
|
||||||
FetchRequest struct {
|
FetchRequest struct {
|
||||||
FetchType FetchRequestType `json:"fetchType"`
|
FetchType FetchRequestType `json:"fetchType"`
|
||||||
Package api.ObjectMeta `json:"package"`
|
Package metav1.ObjectMeta `json:"package"`
|
||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
StorageSvcUrl string `json:"storagesvcurl"`
|
StorageSvcUrl string `json:"storagesvcurl"`
|
||||||
Filename string `json:"filename"`
|
Filename string `json:"filename"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UploadRequest send from builder manager describes which
|
// UploadRequest send from builder manager describes which
|
||||||
@@ -51,8 +50,7 @@ type (
|
|||||||
|
|
||||||
Fetcher struct {
|
Fetcher struct {
|
||||||
sharedVolumePath string
|
sharedVolumePath string
|
||||||
fissionClient *tpr.FissionClient
|
fissionClient *crd.FissionClient
|
||||||
kubeClient *kubernetes.Clientset
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -63,14 +61,13 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func MakeFetcher(sharedVolumePath string) *Fetcher {
|
func MakeFetcher(sharedVolumePath string) *Fetcher {
|
||||||
fissionClient, kubeClient, err := tpr.MakeFissionClient()
|
fissionClient, _, _, err := crd.MakeFissionClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &Fetcher{
|
return &Fetcher{
|
||||||
sharedVolumePath: sharedVolumePath,
|
sharedVolumePath: sharedVolumePath,
|
||||||
fissionClient: fissionClient,
|
fissionClient: fissionClient,
|
||||||
kubeClient: kubeClient,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,12 +78,15 @@ func downloadUrl(url string, localPath string) error {
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(resp.Body)
|
w, err := os.Create(localPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
_, err = io.Copy(w, resp.Body)
|
||||||
err = ioutil.WriteFile(localPath, body, 0600)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = os.Chmod(localPath, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -155,13 +155,11 @@ func (fetcher *Fetcher) FetchHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Error(w, err.Error(), 400)
|
http.Error(w, err.Error(), 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Printf("fetcher received fetch request: %v", req)
|
log.Printf("fetcher received fetch request and started downloading: %v", req)
|
||||||
|
|
||||||
tmpFile := req.Filename + ".tmp"
|
tmpFile := req.Filename + ".tmp"
|
||||||
tmpPath := filepath.Join(fetcher.sharedVolumePath, tmpFile)
|
tmpPath := filepath.Join(fetcher.sharedVolumePath, tmpFile)
|
||||||
|
|
||||||
log.Printf("Start downloading...")
|
|
||||||
|
|
||||||
if req.FetchType == FETCH_URL {
|
if req.FetchType == FETCH_URL {
|
||||||
// fetch the file and save it to the tmp path
|
// fetch the file and save it to the tmp path
|
||||||
err := downloadUrl(req.Url, tmpPath)
|
err := downloadUrl(req.Url, tmpPath)
|
||||||
@@ -286,7 +284,7 @@ func (fetcher *Fetcher) UploadHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("Start uploading...")
|
log.Println("Starting upload...")
|
||||||
ssClient := storageSvcClient.MakeClient(req.StorageSvcUrl)
|
ssClient := storageSvcClient.MakeClient(req.StorageSvcUrl)
|
||||||
|
|
||||||
fileID, err := ssClient.Upload(dstFilepath, nil)
|
fileID, err := ssClient.Upload(dstFilepath, nil)
|
||||||
@@ -332,7 +330,8 @@ func (fetcher *Fetcher) rename(src string, dst string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// archive is a function that zips directory into a zip file
|
// archive zips the contents of directory at src into a new zip file
|
||||||
|
// at dst (note that the contents are zipped, not the directory itself).
|
||||||
func (fetcher *Fetcher) archive(src string, dst string) error {
|
func (fetcher *Fetcher) archive(src string, dst string) error {
|
||||||
var files []string
|
var files []string
|
||||||
target, err := os.Stat(src)
|
target, err := os.Stat(src)
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
FROM golang:1.8.1
|
ARG GO_VERSION=1.9.2
|
||||||
|
|
||||||
|
FROM golang:${GO_VERSION}
|
||||||
|
|
||||||
ENV GOPATH /usr
|
ENV GOPATH /usr
|
||||||
ENV APP ${GOPATH}/src/github.com/fission/fission/environments/go
|
ENV APP ${GOPATH}/src/github.com/fission/fission/environments/go
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
FROM golang:1.8.1
|
ARG BUILDER_IMAGE=fission/builder
|
||||||
|
ARG GO_VERSION=1.9.2
|
||||||
|
|
||||||
|
FROM ${BUILDER_IMAGE}
|
||||||
|
|
||||||
|
FROM golang:${GO_VERSION}
|
||||||
|
|
||||||
|
COPY --from=0 /builder /builder
|
||||||
|
|
||||||
ENV GOPATH /usr
|
ENV GOPATH /usr
|
||||||
RUN go get github.com/fission/fission
|
RUN go get github.com/fission/fission
|
||||||
|
|
||||||
|
ADD build.sh /usr/local/bin/build
|
||||||
|
|
||||||
|
|||||||
Executable
+4
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
cd ${SRC_PKG}
|
||||||
|
go build -buildmode=plugin -i -o ${DEPLOY_PKG} .
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [ $# -eq 0 ]
|
|
||||||
then
|
|
||||||
echo "No arguments, building current dir"
|
|
||||||
filename='.'
|
|
||||||
else
|
|
||||||
filename=$1
|
|
||||||
fi
|
|
||||||
|
|
||||||
docker run --rm -v $(pwd):/build -w /build fission/go-builder:1.8.1 go build -buildmode=plugin -o function.so $filename && echo "Compiled plugin: function.so. Use 'fission function create' to upload to fission."
|
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"plugin"
|
"plugin"
|
||||||
|
|
||||||
"github.com/fission/fission/environments/go/context"
|
"github.com/fission/fission/environments/go/context"
|
||||||
@@ -13,14 +16,52 @@ const (
|
|||||||
CODE_PATH = "/userfunc/user"
|
CODE_PATH = "/userfunc/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
FunctionLoadRequest struct {
|
||||||
|
// FilePath is an absolute filesystem path to the
|
||||||
|
// function. What exactly is stored here is
|
||||||
|
// env-specific. Optional.
|
||||||
|
FilePath string `json:"filepath"`
|
||||||
|
|
||||||
|
// FunctionName has an environment-specific meaning;
|
||||||
|
// usually, it defines a function within a module
|
||||||
|
// containing multiple functions. Optional; default is
|
||||||
|
// environment-specific.
|
||||||
|
FunctionName string `json:"functionName"`
|
||||||
|
|
||||||
|
// URL to expose this function at. Optional; defaults
|
||||||
|
// to "/".
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
var userFunc http.HandlerFunc
|
var userFunc http.HandlerFunc
|
||||||
|
|
||||||
func loadPlugin() http.HandlerFunc {
|
func loadPlugin(codePath, entrypoint string) http.HandlerFunc {
|
||||||
p, err := plugin.Open(CODE_PATH)
|
|
||||||
|
// if codepath's a directory, load the file inside it
|
||||||
|
info, err := os.Stat(codePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
sym, err := p.Lookup("Handler")
|
if info.IsDir() {
|
||||||
|
files, err := ioutil.ReadDir(codePath)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if len(files) == 0 {
|
||||||
|
panic("No files to load")
|
||||||
|
}
|
||||||
|
fi := files[0]
|
||||||
|
codePath = filepath.Join(codePath, fi.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("loading plugin from %v\n", codePath)
|
||||||
|
p, err := plugin.Open(codePath)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
sym, err := p.Lookup(entrypoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Entry point not found")
|
panic("Entry point not found")
|
||||||
}
|
}
|
||||||
@@ -44,7 +85,7 @@ func loadPlugin() http.HandlerFunc {
|
|||||||
|
|
||||||
func specializeHandler(w http.ResponseWriter, r *http.Request) {
|
func specializeHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if userFunc != nil {
|
if userFunc != nil {
|
||||||
w.WriteHeader(400)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
w.Write([]byte("Not a generic container"))
|
w.Write([]byte("Not a generic container"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -61,12 +102,48 @@ func specializeHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("Specializing ...")
|
fmt.Println("Specializing ...")
|
||||||
userFunc = loadPlugin()
|
userFunc = loadPlugin(CODE_PATH, "Handler")
|
||||||
|
fmt.Println("Done")
|
||||||
|
}
|
||||||
|
|
||||||
|
func specializeHandlerV2(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if userFunc != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
w.Write([]byte("Not a generic container"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var loadreq FunctionLoadRequest
|
||||||
|
err = json.Unmarshal(body, &loadreq)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = os.Stat(loadreq.FilePath)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
w.Write([]byte(CODE_PATH + ": not found"))
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Specializing ...")
|
||||||
|
userFunc = loadPlugin(loadreq.FilePath, loadreq.FunctionName)
|
||||||
fmt.Println("Done")
|
fmt.Println("Done")
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
http.HandleFunc("/specialize", specializeHandler)
|
http.HandleFunc("/specialize", specializeHandler)
|
||||||
|
http.HandleFunc("/v2/specialize", specializeHandlerV2)
|
||||||
|
|
||||||
// Generic route -- all http requests go to the user function.
|
// Generic route -- all http requests go to the user function.
|
||||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|||||||
@@ -1,7 +1,18 @@
|
|||||||
# A docker image for the func container.
|
# A docker image for the func container.
|
||||||
|
|
||||||
FROM node:8-onbuild
|
# default variant is the official alpine node image (much smaller than the standard image)
|
||||||
|
FROM node:8-alpine
|
||||||
|
|
||||||
ADD server.js /usr/src/app/server.js
|
ARG NODE_ENV
|
||||||
|
ENV NODE_ENV $NODE_ENV
|
||||||
|
|
||||||
EXPOSE 8888
|
RUN mkdir -p /usr/src/app
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
COPY package.json /usr/src/app/
|
||||||
|
RUN npm install && npm cache clean --force
|
||||||
|
COPY server.js /usr/src/app/server.js
|
||||||
|
|
||||||
|
CMD [ "npm", "start" ]
|
||||||
|
|
||||||
|
EXPOSE 8888
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# A docker image for the func container.
|
||||||
|
|
||||||
|
# debian variant is the official standard node image (larger than the alpine image)
|
||||||
|
FROM node:8
|
||||||
|
|
||||||
|
ARG NODE_ENV
|
||||||
|
ENV NODE_ENV $NODE_ENV
|
||||||
|
|
||||||
|
RUN mkdir -p /usr/src/app
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
COPY package.json /usr/src/app/
|
||||||
|
RUN npm install && npm cache clean --force
|
||||||
|
COPY server.js /usr/src/app/server.js
|
||||||
|
|
||||||
|
CMD [ "npm", "start" ]
|
||||||
|
|
||||||
|
EXPOSE 8888
|
||||||
@@ -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"]
|
||||||
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
FROM alpine:3.5
|
ARG BUILDER_IMAGE=fission/builder:latest
|
||||||
|
FROM ${BUILDER_IMAGE}
|
||||||
|
|
||||||
RUN apk update
|
RUN apk update
|
||||||
RUN apk add --no-cache python3 python3-dev build-base
|
RUN apk add --no-cache python3 python3-dev build-base
|
||||||
@@ -6,6 +7,5 @@ RUN pip3 install --upgrade pip
|
|||||||
RUN rm -r /root/.cache
|
RUN rm -r /root/.cache
|
||||||
|
|
||||||
ADD defaultBuildCmd /usr/local/bin/build
|
ADD defaultBuildCmd /usr/local/bin/build
|
||||||
ADD builder /builder
|
|
||||||
|
|
||||||
EXPOSE 8001
|
EXPOSE 8001
|
||||||
@@ -24,12 +24,41 @@ def loadv2():
|
|||||||
global userfunc
|
global userfunc
|
||||||
body = request.get_json()
|
body = request.get_json()
|
||||||
filepath = body['filepath']
|
filepath = body['filepath']
|
||||||
functionName = body['functionName']
|
handler = body['functionName']
|
||||||
# add filepath into syspath for module import
|
|
||||||
sys.path.append(filepath)
|
# The value of "functionName" is consist of `<module-name>.<function-name>`.
|
||||||
fn, path, desc = imp.find_module('user', [filepath])
|
moduleName, funcName = handler.split(".")
|
||||||
mod = imp.load_module('user', fn, path, desc)
|
|
||||||
userfunc = getattr(mod, functionName)
|
# check whether the destination is a directory or a file
|
||||||
|
if os.path.isdir(filepath):
|
||||||
|
# add package directory path into module search path
|
||||||
|
sys.path.append(filepath)
|
||||||
|
|
||||||
|
# find module from package path we append previously.
|
||||||
|
# Python will try to find module from the same name file under
|
||||||
|
# the package directory. If search is successful, the return
|
||||||
|
# value is a 3-element tuple; otherwise, an exception "ImportError"
|
||||||
|
# is raised.
|
||||||
|
# Second parameter of find_module enforces python to find same
|
||||||
|
# name module from the given list of directories to prevent name
|
||||||
|
# confliction with built-in modules.
|
||||||
|
f, path, desc = imp.find_module(moduleName, [filepath])
|
||||||
|
|
||||||
|
# load module
|
||||||
|
# Return module object is the load is successful; otherwise,
|
||||||
|
# an exception is raised.
|
||||||
|
try:
|
||||||
|
mod = imp.load_module(moduleName, f, path, desc)
|
||||||
|
finally:
|
||||||
|
if f:
|
||||||
|
f.close()
|
||||||
|
else:
|
||||||
|
# load source from destination python file
|
||||||
|
mod = imp.load_source(moduleName, filepath)
|
||||||
|
|
||||||
|
# load user function from module
|
||||||
|
userfunc = getattr(mod, funcName)
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@app.route('/', methods=['GET', 'POST', 'PUT', 'HEAD', 'OPTIONS', 'DELETE'])
|
@app.route('/', methods=['GET', 'POST', 'PUT', 'HEAD', 'OPTIONS', 'DELETE'])
|
||||||
@@ -66,4 +95,4 @@ def setup_logger(loglevel):
|
|||||||
#
|
#
|
||||||
setup_logger(logging.DEBUG)
|
setup_logger(logging.DEBUG)
|
||||||
app.logger.info("Starting server")
|
app.logger.info("Starting server")
|
||||||
app.run(host='0.0.0.0', port='8888')
|
app.run(host='0.0.0.0', port=8888)
|
||||||
@@ -2,12 +2,19 @@
|
|||||||
|
|
||||||
This directory contains several examples to get you started using Node.js with Fission.
|
This directory contains several examples to get you started using Node.js with Fission.
|
||||||
|
|
||||||
|
## Environment
|
||||||
|
|
||||||
Before running any of these functions, make sure you have created a `nodejs` Fission environment:
|
Before running any of these functions, make sure you have created a `nodejs` Fission environment:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ fission env create --name nodejs --image fission/node-env
|
$ fission env create --name nodejs --image fission/node-env
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Note: The default `fission/node-env` image is based on Alpine, which is much smaller than the main Debian Node image (65MB vs 680MB) while still being suitable for most use cases.
|
||||||
|
If you need to use the full Debian image use the `fission/node-env-debian` image instead.
|
||||||
|
See the [official Node docker hub repo](https://hub.docker.com/_/node/) for considerations
|
||||||
|
relating to this choice.
|
||||||
|
|
||||||
## Function signature
|
## Function signature
|
||||||
|
|
||||||
Every Node.js function has the same basic form:
|
Every Node.js function has the same basic form:
|
||||||
@@ -75,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
|
||||||
@@ -96,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"}
|
||||||
|
```
|
||||||
@@ -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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.
|
||||||
|
|
||||||
@@ -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"))
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Hello, world!
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
def readFile(name):
|
||||||
|
with open(name) as f:
|
||||||
|
return f.read()
|
||||||
@@ -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
|
||||||
+108
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
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 executor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gorilla/handlers"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
"github.com/fission/fission"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (executor *Executor) getServiceForFunctionApi(w http.ResponseWriter, r *http.Request) {
|
||||||
|
body, err := ioutil.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Failed to read request", 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// get function metadata
|
||||||
|
m := metav1.ObjectMeta{}
|
||||||
|
err = json.Unmarshal(body, &m)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Failed to parse request", 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceName, err := executor.getServiceForFunction(&m)
|
||||||
|
if err != nil {
|
||||||
|
code, msg := fission.GetHTTPError(err)
|
||||||
|
log.Printf("Error: %v: %v", code, msg)
|
||||||
|
http.Error(w, msg, code)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Write([]byte(serviceName))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (executor *Executor) getServiceForFunction(m *metav1.ObjectMeta) (string, error) {
|
||||||
|
// Check function -> svc cache
|
||||||
|
log.Printf("[%v] Checking for cached function service", m.Name)
|
||||||
|
fsvc, err := executor.fsCache.GetByFunction(m)
|
||||||
|
if err == nil {
|
||||||
|
// Cached, return svc address
|
||||||
|
return fsvc.Address, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
respChan := make(chan *createFuncServiceResponse)
|
||||||
|
executor.requestChan <- &createFuncServiceRequest{
|
||||||
|
funcMeta: m,
|
||||||
|
respChan: respChan,
|
||||||
|
}
|
||||||
|
resp := <-respChan
|
||||||
|
if resp.err != nil {
|
||||||
|
return "", resp.err
|
||||||
|
}
|
||||||
|
return resp.funcSvc.Address, resp.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// find funcSvc and update its atime
|
||||||
|
func (executor *Executor) tapService(w http.ResponseWriter, r *http.Request) {
|
||||||
|
body, err := ioutil.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "Failed to read request", 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
svcName := string(body)
|
||||||
|
svcHost := strings.TrimPrefix(svcName, "http://")
|
||||||
|
|
||||||
|
err = executor.fsCache.TouchByAddress(svcHost)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("funcSvc tap error: %v", err)
|
||||||
|
http.Error(w, "Not found", 404)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (executor *Executor) Serve(port int) {
|
||||||
|
r := mux.NewRouter()
|
||||||
|
r.HandleFunc("/v2/getServiceForFunction", executor.getServiceForFunctionApi).Methods("POST")
|
||||||
|
r.HandleFunc("/v2/tapService", executor.tapService).Methods("POST")
|
||||||
|
address := fmt.Sprintf(":%v", port)
|
||||||
|
log.Printf("starting executor at port %v", port)
|
||||||
|
log.Fatal(http.ListenAndServe(address, handlers.LoggingHandler(os.Stdout, r)))
|
||||||
|
}
|
||||||
@@ -26,20 +26,20 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
poolmgrUrl string
|
executorUrl string
|
||||||
tappedByUrl map[string]bool
|
tappedByUrl map[string]bool
|
||||||
requestChan chan string
|
requestChan chan string
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeClient(poolmgrUrl string) *Client {
|
func MakeClient(executorUrl string) *Client {
|
||||||
c := &Client{
|
c := &Client{
|
||||||
poolmgrUrl: strings.TrimSuffix(poolmgrUrl, "/"),
|
executorUrl: strings.TrimSuffix(executorUrl, "/"),
|
||||||
tappedByUrl: make(map[string]bool),
|
tappedByUrl: make(map[string]bool),
|
||||||
requestChan: make(chan string),
|
requestChan: make(chan string),
|
||||||
}
|
}
|
||||||
@@ -47,15 +47,15 @@ func MakeClient(poolmgrUrl string) *Client {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetServiceForFunction(metadata *api.ObjectMeta) (string, error) {
|
func (c *Client) GetServiceForFunction(metadata *metav1.ObjectMeta) (string, error) {
|
||||||
poolmgrUrl := c.poolmgrUrl + "/v2/getServiceForFunction"
|
executorUrl := c.executorUrl + "/v2/getServiceForFunction"
|
||||||
|
|
||||||
body, err := json.Marshal(metadata)
|
body, err := json.Marshal(metadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := http.Post(poolmgrUrl, "application/json", bytes.NewReader(body))
|
resp, err := http.Post(executorUrl, "application/json", bytes.NewReader(body))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -100,9 +100,9 @@ func (c *Client) TapService(serviceUrl *url.URL) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) _tapService(serviceUrlStr string) error {
|
func (c *Client) _tapService(serviceUrlStr string) error {
|
||||||
poolmgrUrl := c.poolmgrUrl + "/v2/tapService"
|
executorUrl := c.executorUrl + "/v2/tapService"
|
||||||
|
|
||||||
resp, err := http.Post(poolmgrUrl, "application/octet-stream", bytes.NewReader([]byte(serviceUrlStr)))
|
resp, err := http.Post(executorUrl, "application/octet-stream", bytes.NewReader([]byte(serviceUrlStr)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
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 deploymgr
|
||||||
|
|
||||||
|
func GetFuncSvc() (*funcSvc, error) {
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
/*
|
||||||
|
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 executor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/dchest/uniuri"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
"github.com/fission/fission/cache"
|
||||||
|
"github.com/fission/fission/crd"
|
||||||
|
"github.com/fission/fission/executor/fscache"
|
||||||
|
"github.com/fission/fission/executor/poolmgr"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Executor struct {
|
||||||
|
gpm *poolmgr.GenericPoolManager
|
||||||
|
functionEnv *cache.Cache
|
||||||
|
fissionClient *crd.FissionClient
|
||||||
|
fsCache *fscache.FunctionServiceCache
|
||||||
|
|
||||||
|
requestChan chan *createFuncServiceRequest
|
||||||
|
fsCreateWg map[string]*sync.WaitGroup
|
||||||
|
}
|
||||||
|
createFuncServiceRequest struct {
|
||||||
|
funcMeta *metav1.ObjectMeta
|
||||||
|
respChan chan *createFuncServiceResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
createFuncServiceResponse struct {
|
||||||
|
funcSvc *fscache.FuncSvc
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func MakeExecutor(gpm *poolmgr.GenericPoolManager, fissionClient *crd.FissionClient, fsCache *fscache.FunctionServiceCache) *Executor {
|
||||||
|
executor := &Executor{
|
||||||
|
gpm: gpm,
|
||||||
|
functionEnv: cache.MakeCache(10*time.Second, 0),
|
||||||
|
fissionClient: fissionClient,
|
||||||
|
fsCache: fsCache,
|
||||||
|
|
||||||
|
requestChan: make(chan *createFuncServiceRequest),
|
||||||
|
fsCreateWg: make(map[string]*sync.WaitGroup),
|
||||||
|
}
|
||||||
|
go executor.serveCreateFuncServices()
|
||||||
|
return executor
|
||||||
|
}
|
||||||
|
|
||||||
|
// All non-cached function service requests go through this goroutine
|
||||||
|
// serially. It parallelizes requests for different functions, and
|
||||||
|
// ensures that for a given function, only one request causes a pod to
|
||||||
|
// get specialized. In other words, it ensures that when there's an
|
||||||
|
// ongoing request for a certain function, all other requests wait for
|
||||||
|
// that request to complete.
|
||||||
|
func (executor *Executor) serveCreateFuncServices() {
|
||||||
|
for {
|
||||||
|
req := <-executor.requestChan
|
||||||
|
m := req.funcMeta
|
||||||
|
|
||||||
|
// Cache miss -- is this first one to request the func?
|
||||||
|
wg, found := executor.fsCreateWg[crd.CacheKey(m)]
|
||||||
|
if !found {
|
||||||
|
// create a waitgroup for other requests for
|
||||||
|
// the same function to wait on
|
||||||
|
wg := &sync.WaitGroup{}
|
||||||
|
wg.Add(1)
|
||||||
|
executor.fsCreateWg[crd.CacheKey(m)] = wg
|
||||||
|
|
||||||
|
// launch a goroutine for each request, to parallelize
|
||||||
|
// the specialization of different functions
|
||||||
|
go func() {
|
||||||
|
fsvc, err := executor.createServiceForFunction(m)
|
||||||
|
req.respChan <- &createFuncServiceResponse{
|
||||||
|
funcSvc: fsvc,
|
||||||
|
err: err,
|
||||||
|
}
|
||||||
|
delete(executor.fsCreateWg, crd.CacheKey(m))
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
} else {
|
||||||
|
// There's an existing request for this function, wait for it to finish
|
||||||
|
go func() {
|
||||||
|
log.Printf("Waiting for concurrent request for the same function: %v", m)
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
// get the function service from the cache
|
||||||
|
fsvc, err := executor.fsCache.GetByFunction(m)
|
||||||
|
req.respChan <- &createFuncServiceResponse{
|
||||||
|
funcSvc: fsvc,
|
||||||
|
err: err,
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (executor *Executor) createServiceForFunction(m *metav1.ObjectMeta) (*fscache.FuncSvc, error) {
|
||||||
|
log.Printf("[%v] No cached function service found, creating one", m.Name)
|
||||||
|
|
||||||
|
env, err := executor.getFunctionEnv(m)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Appropriate backend handles the service creation
|
||||||
|
backend := os.Getenv("EXECUTOR_BACKEND")
|
||||||
|
switch backend {
|
||||||
|
case "DEPLOY":
|
||||||
|
return nil, nil
|
||||||
|
default:
|
||||||
|
pool, err := executor.gpm.GetPool(env)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// from GenericPool -> get one function container
|
||||||
|
// (this also adds to the cache)
|
||||||
|
log.Printf("[%v] getting function service from pool", m.Name)
|
||||||
|
fsvc, err := pool.GetFuncSvc(m)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return fsvc, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (executor *Executor) getFunctionEnv(m *metav1.ObjectMeta) (*crd.Environment, error) {
|
||||||
|
var env *crd.Environment
|
||||||
|
|
||||||
|
// Cached ?
|
||||||
|
result, err := executor.functionEnv.Get(crd.CacheKey(m))
|
||||||
|
if err == nil {
|
||||||
|
env = result.(*crd.Environment)
|
||||||
|
return env, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache miss -- get func from controller
|
||||||
|
f, err := executor.fissionClient.Functions(m.Namespace).Get(m.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get env from metadata
|
||||||
|
log.Printf("[%v] getting env", m)
|
||||||
|
env, err = executor.fissionClient.Environments(f.Spec.Environment.Namespace).Get(f.Spec.Environment.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache for future lookups
|
||||||
|
executor.functionEnv.Set(crd.CacheKey(m), env)
|
||||||
|
|
||||||
|
return env, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartExecutor Starts executor and the backend components that executor uses such as Poolmgr,
|
||||||
|
// deploymgr and potential future backends
|
||||||
|
func StartExecutor(fissionNamespace string, functionNamespace string, port int) error {
|
||||||
|
fissionClient, kubernetesClient, _, err := crd.MakeFissionClient()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Failed to get kubernetes client: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
instanceID := uniuri.NewLen(8)
|
||||||
|
poolmgr.CleanupOldPoolmgrResources(kubernetesClient, functionNamespace, instanceID)
|
||||||
|
|
||||||
|
fsCache := fscache.MakeFunctionServiceCache()
|
||||||
|
gpm := poolmgr.MakeGenericPoolManager(
|
||||||
|
fissionClient, kubernetesClient, fissionNamespace,
|
||||||
|
functionNamespace, fsCache, instanceID)
|
||||||
|
|
||||||
|
api := MakeExecutor(gpm, fissionClient, fsCache)
|
||||||
|
go api.Serve(port)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -20,10 +20,11 @@
|
|||||||
// Here's how I run this on my setup, with minikube:
|
// Here's how I run this on my setup, with minikube:
|
||||||
// TEST_SPECIALIZE_URL=http://192.168.99.100:30002/specialize TEST_FETCHER_URL=http://192.168.99.100:30001 FETCHER_IMAGE=minikube/fetcher:testing KUBECONFIG=/Users/soam/.kube/config go test -v .
|
// TEST_SPECIALIZE_URL=http://192.168.99.100:30002/specialize TEST_FETCHER_URL=http://192.168.99.100:30001 FETCHER_IMAGE=minikube/fetcher:testing KUBECONFIG=/Users/soam/.kube/config go test -v .
|
||||||
|
|
||||||
package poolmgr
|
package executor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -31,22 +32,21 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/kubernetes"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/client-go/1.5/pkg/api/v1"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
"k8s.io/client-go/1.5/pkg/labels"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/1.5/pkg/util/intstr"
|
apiv1 "k8s.io/client-go/pkg/api/v1"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/poolmgr/client"
|
"github.com/fission/fission/crd"
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/executor/client"
|
||||||
"io/ioutil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// return the number of pods in the given namespace matching the given labels
|
// return the number of pods in the given namespace matching the given labels
|
||||||
func countPods(kubeClient *kubernetes.Clientset, ns string, labelz map[string]string) int {
|
func countPods(kubeClient *kubernetes.Clientset, ns string, labelz map[string]string) int {
|
||||||
pods, err := kubeClient.Pods(ns).List(api.ListOptions{
|
pods, err := kubeClient.Pods(ns).List(metav1.ListOptions{
|
||||||
LabelSelector: labels.Set(labelz).AsSelector(),
|
LabelSelector: labels.Set(labelz).AsSelector().String(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("Failed to list pods: %v", err)
|
log.Panicf("Failed to list pods: %v", err)
|
||||||
@@ -55,8 +55,8 @@ func countPods(kubeClient *kubernetes.Clientset, ns string, labelz map[string]st
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createTestNamespace(kubeClient *kubernetes.Clientset, ns string) {
|
func createTestNamespace(kubeClient *kubernetes.Clientset, ns string) {
|
||||||
_, err := kubeClient.Namespaces().Create(&v1.Namespace{
|
_, err := kubeClient.Namespaces().Create(&apiv1.Namespace{
|
||||||
ObjectMeta: v1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: ns,
|
Name: ns,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -67,16 +67,16 @@ func createTestNamespace(kubeClient *kubernetes.Clientset, ns string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create a nodeport service
|
// create a nodeport service
|
||||||
func createSvc(kubeClient *kubernetes.Clientset, ns string, name string, targetPort int, nodePort int32, labels map[string]string) *v1.Service {
|
func createSvc(kubeClient *kubernetes.Clientset, ns string, name string, targetPort int, nodePort int32, labels map[string]string) *apiv1.Service {
|
||||||
svc, err := kubeClient.Services(ns).Create(&v1.Service{
|
svc, err := kubeClient.Services(ns).Create(&apiv1.Service{
|
||||||
ObjectMeta: v1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
},
|
},
|
||||||
Spec: v1.ServiceSpec{
|
Spec: apiv1.ServiceSpec{
|
||||||
Type: v1.ServiceTypeNodePort,
|
Type: apiv1.ServiceTypeNodePort,
|
||||||
Ports: []v1.ServicePort{
|
Ports: []apiv1.ServicePort{
|
||||||
{
|
{
|
||||||
Protocol: v1.ProtocolTCP,
|
Protocol: apiv1.ProtocolTCP,
|
||||||
Port: 80,
|
Port: 80,
|
||||||
TargetPort: intstr.FromInt(targetPort),
|
TargetPort: intstr.FromInt(targetPort),
|
||||||
NodePort: nodePort,
|
NodePort: nodePort,
|
||||||
@@ -104,7 +104,7 @@ func httpGet(url string) string {
|
|||||||
return string(body)
|
return string(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPoolmgr(t *testing.T) {
|
func TestExecutor(t *testing.T) {
|
||||||
// run in a random namespace so we can have concurrent tests
|
// run in a random namespace so we can have concurrent tests
|
||||||
// on a given cluster
|
// on a given cluster
|
||||||
rand.Seed(time.Now().UTC().UnixNano())
|
rand.Seed(time.Now().UTC().UnixNano())
|
||||||
@@ -120,8 +120,8 @@ func TestPoolmgr(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// connect to k8s
|
// connect to k8s
|
||||||
// and get TPR client
|
// and get CRD client
|
||||||
fissionClient, kubeClient, err := tpr.MakeFissionClient()
|
fissionClient, kubeClient, apiExtClient, err := crd.MakeFissionClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("failed to connect: %v", err)
|
log.Panicf("failed to connect: %v", err)
|
||||||
}
|
}
|
||||||
@@ -133,16 +133,16 @@ func TestPoolmgr(t *testing.T) {
|
|||||||
createTestNamespace(kubeClient, functionNs)
|
createTestNamespace(kubeClient, functionNs)
|
||||||
defer kubeClient.Namespaces().Delete(functionNs, nil)
|
defer kubeClient.Namespaces().Delete(functionNs, nil)
|
||||||
|
|
||||||
// make sure TPR types exist on cluster
|
// make sure CRD types exist on cluster
|
||||||
err = tpr.EnsureFissionTPRs(kubeClient)
|
err = crd.EnsureFissionCRDs(apiExtClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("failed to ensure tprs: %v", err)
|
log.Panicf("failed to ensure crds: %v", err)
|
||||||
}
|
}
|
||||||
fissionClient.WaitForTPRs()
|
fissionClient.WaitForCRDs()
|
||||||
|
|
||||||
// create an env on the cluster
|
// create an env on the cluster
|
||||||
env, err := fissionClient.Environments(fissionNs).Create(&tpr.Environment{
|
env, err := fissionClient.Environments(fissionNs).Create(&crd.Environment{
|
||||||
Metadata: api.ObjectMeta{
|
Metadata: metav1.ObjectMeta{
|
||||||
Name: "nodejs",
|
Name: "nodejs",
|
||||||
Namespace: fissionNs,
|
Namespace: fissionNs,
|
||||||
},
|
},
|
||||||
@@ -160,7 +160,7 @@ func TestPoolmgr(t *testing.T) {
|
|||||||
|
|
||||||
// create poolmgr
|
// create poolmgr
|
||||||
port := 9999
|
port := 9999
|
||||||
err = StartPoolmgr(fissionNs, functionNs, port)
|
err = StartExecutor(fissionNs, functionNs, port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("failed to start poolmgr: %v", err)
|
log.Panicf("failed to start poolmgr: %v", err)
|
||||||
}
|
}
|
||||||
@@ -173,37 +173,47 @@ func TestPoolmgr(t *testing.T) {
|
|||||||
// waitForPool(functionNs, "nodejs")
|
// waitForPool(functionNs, "nodejs")
|
||||||
time.Sleep(6 * time.Second)
|
time.Sleep(6 * time.Second)
|
||||||
|
|
||||||
|
envRef := fission.EnvironmentReference{
|
||||||
|
Namespace: env.Metadata.Namespace,
|
||||||
|
Name: env.Metadata.Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
deployment := fission.Archive{
|
||||||
|
Type: fission.ArchiveTypeLiteral,
|
||||||
|
Literal: []byte(`module.exports = async function(context) { return { status: 200, body: "Hello, world!\n" }; }`),
|
||||||
|
}
|
||||||
|
|
||||||
// create a package
|
// create a package
|
||||||
p := &tpr.Package{
|
p := &crd.Package{
|
||||||
Metadata: api.ObjectMeta{
|
Metadata: metav1.ObjectMeta{
|
||||||
Name: "hello",
|
Name: "hello",
|
||||||
Namespace: fissionNs,
|
Namespace: fissionNs,
|
||||||
},
|
},
|
||||||
Spec: fission.PackageSpec{
|
Spec: fission.PackageSpec{
|
||||||
Type: fission.PackageTypeLiteral,
|
Environment: envRef,
|
||||||
Literal: []byte(`module.exports = async function(context) { return { status: 200, body: "Hello, world!\n" }; }`),
|
Deployment: deployment,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err = fissionClient.Packages(fissionNs).Create(p)
|
p, err = fissionClient.Packages(fissionNs).Create(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panicf("failed to create package: %v", err)
|
log.Panicf("failed to create package: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a function
|
// create a function
|
||||||
f := &tpr.Function{
|
f := &crd.Function{
|
||||||
Metadata: api.ObjectMeta{
|
Metadata: metav1.ObjectMeta{
|
||||||
Name: "hello",
|
Name: "hello",
|
||||||
Namespace: fissionNs,
|
Namespace: fissionNs,
|
||||||
},
|
},
|
||||||
Spec: fission.FunctionSpec{
|
Spec: fission.FunctionSpec{
|
||||||
Source: fission.FunctionPackageRef{},
|
Environment: envRef,
|
||||||
Deployment: fission.FunctionPackageRef{
|
Package: fission.FunctionPackageRef{
|
||||||
PackageRef: fission.PackageRef{
|
PackageRef: fission.PackageRef{
|
||||||
Name: p.Metadata.Name,
|
Namespace: p.Metadata.Namespace,
|
||||||
Namespace: p.Metadata.Namespace,
|
Name: p.Metadata.Name,
|
||||||
|
ResourceVersion: p.Metadata.ResourceVersion,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
EnvironmentName: env.Metadata.Name,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err = fissionClient.Functions(fissionNs).Create(f)
|
_, err = fissionClient.Functions(fissionNs).Create(f)
|
||||||
@@ -0,0 +1,230 @@
|
|||||||
|
/*
|
||||||
|
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 fscache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/client-go/pkg/api"
|
||||||
|
|
||||||
|
"github.com/fission/fission"
|
||||||
|
"github.com/fission/fission/cache"
|
||||||
|
"github.com/fission/fission/crd"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fscRequestType int
|
||||||
|
type backendType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
TOUCH fscRequestType = iota
|
||||||
|
LISTOLD
|
||||||
|
LOG
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
POOLMGR backendType = iota
|
||||||
|
NEWDEPLOY
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
FuncSvc struct {
|
||||||
|
Function *metav1.ObjectMeta // function this pod/service is for
|
||||||
|
Environment *crd.Environment // function's environment
|
||||||
|
Address string // Host:Port or IP:Port that the function's service can be reached at.
|
||||||
|
KubernetesObjects []api.ObjectReference // Kubernetes Objects (within the function namespace)
|
||||||
|
Backend backendType
|
||||||
|
|
||||||
|
Ctime time.Time
|
||||||
|
Atime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionServiceCache struct {
|
||||||
|
byFunction *cache.Cache // function-key -> funcSvc : map[string]*funcSvc
|
||||||
|
byAddress *cache.Cache // address -> function : map[string]metav1.ObjectMeta
|
||||||
|
|
||||||
|
requestChannel chan *fscRequest
|
||||||
|
}
|
||||||
|
fscRequest struct {
|
||||||
|
requestType fscRequestType
|
||||||
|
address string
|
||||||
|
kubernetesObjects []api.ObjectReference
|
||||||
|
age time.Duration
|
||||||
|
env *metav1.ObjectMeta // used for ListOld
|
||||||
|
responseChannel chan *fscResponse
|
||||||
|
}
|
||||||
|
fscResponse struct {
|
||||||
|
objects []*FuncSvc
|
||||||
|
deleted bool
|
||||||
|
error
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func MakeFunctionServiceCache() *FunctionServiceCache {
|
||||||
|
fsc := &FunctionServiceCache{
|
||||||
|
byFunction: cache.MakeCache(0, 0),
|
||||||
|
byAddress: cache.MakeCache(0, 0),
|
||||||
|
requestChannel: make(chan *fscRequest),
|
||||||
|
}
|
||||||
|
go fsc.service()
|
||||||
|
return fsc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fsc *FunctionServiceCache) service() {
|
||||||
|
for {
|
||||||
|
req := <-fsc.requestChannel
|
||||||
|
resp := &fscResponse{}
|
||||||
|
switch req.requestType {
|
||||||
|
case TOUCH:
|
||||||
|
// update atime for this function svc
|
||||||
|
resp.error = fsc._touchByAddress(req.address)
|
||||||
|
case LISTOLD:
|
||||||
|
// get svcs idle for > req.age
|
||||||
|
fscs := fsc.byFunction.Copy()
|
||||||
|
funcObjects := make([]*FuncSvc, 0)
|
||||||
|
for _, funcSvc := range fscs {
|
||||||
|
fsvc := funcSvc.(*FuncSvc)
|
||||||
|
if fsvc.Environment.Metadata.UID == req.env.UID &&
|
||||||
|
time.Now().Sub(fsvc.Atime) > req.age {
|
||||||
|
funcObjects = append(funcObjects, fsvc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resp.objects = funcObjects
|
||||||
|
case LOG:
|
||||||
|
funcCopy := fsc.byFunction.Copy()
|
||||||
|
log.Printf("Cache has %v entries", len(funcCopy))
|
||||||
|
for key, fsvcI := range funcCopy {
|
||||||
|
fsvc := fsvcI.(*FuncSvc)
|
||||||
|
for _, kubeObj := range fsvc.KubernetesObjects {
|
||||||
|
log.Printf("%v\t%v\t%v", key, kubeObj.Kind, kubeObj.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
req.responseChannel <- resp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fsc *FunctionServiceCache) GetByFunction(m *metav1.ObjectMeta) (*FuncSvc, error) {
|
||||||
|
key := crd.CacheKey(m)
|
||||||
|
|
||||||
|
fsvcI, err := fsc.byFunction.Get(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// update atime
|
||||||
|
fsvc := fsvcI.(*FuncSvc)
|
||||||
|
fsvc.Atime = time.Now()
|
||||||
|
|
||||||
|
fsvcCopy := *fsvc
|
||||||
|
return &fsvcCopy, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: error should be second return
|
||||||
|
func (fsc *FunctionServiceCache) Add(fsvc FuncSvc) (error, *FuncSvc) {
|
||||||
|
err, existing := fsc.byFunction.Set(crd.CacheKey(fsvc.Function), &fsvc)
|
||||||
|
if err != nil {
|
||||||
|
if existing != nil {
|
||||||
|
f := existing.(*FuncSvc)
|
||||||
|
err2 := fsc.TouchByAddress(f.Address)
|
||||||
|
if err2 != nil {
|
||||||
|
return err2, nil
|
||||||
|
}
|
||||||
|
fCopy := *f
|
||||||
|
return err, &fCopy
|
||||||
|
}
|
||||||
|
return err, nil
|
||||||
|
}
|
||||||
|
now := time.Now()
|
||||||
|
fsvc.Ctime = now
|
||||||
|
fsvc.Atime = now
|
||||||
|
|
||||||
|
// Add to byAddress cache. Ignore NameExists errors
|
||||||
|
// because of multiple-specialization. See issue #331.
|
||||||
|
err, _ = fsc.byAddress.Set(fsvc.Address, *fsvc.Function)
|
||||||
|
if err != nil {
|
||||||
|
if fe, ok := err.(fission.Error); ok {
|
||||||
|
if fe.Code == fission.ErrorNameExists {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Printf("error caching fsvc: %v", err)
|
||||||
|
return err, nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fsc *FunctionServiceCache) TouchByAddress(address string) error {
|
||||||
|
responseChannel := make(chan *fscResponse)
|
||||||
|
fsc.requestChannel <- &fscRequest{
|
||||||
|
requestType: TOUCH,
|
||||||
|
address: address,
|
||||||
|
responseChannel: responseChannel,
|
||||||
|
}
|
||||||
|
resp := <-responseChannel
|
||||||
|
return resp.error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fsc *FunctionServiceCache) _touchByAddress(address string) error {
|
||||||
|
mI, err := fsc.byAddress.Get(address)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
m := mI.(metav1.ObjectMeta)
|
||||||
|
fsvcI, err := fsc.byFunction.Get(crd.CacheKey(&m))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fsvc := fsvcI.(*FuncSvc)
|
||||||
|
fsvc.Atime = time.Now()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fsc *FunctionServiceCache) DeleteOld(fsvc *FuncSvc, minAge time.Duration) (bool, error) {
|
||||||
|
if time.Now().Sub(fsvc.Atime) < minAge {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fsc.byFunction.Delete(crd.CacheKey(fsvc.Function))
|
||||||
|
fsc.byAddress.Delete(fsvc.Address)
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fsc *FunctionServiceCache) ListOld(env *metav1.ObjectMeta, age time.Duration) ([]*FuncSvc, error) {
|
||||||
|
responseChannel := make(chan *fscResponse)
|
||||||
|
fsc.requestChannel <- &fscRequest{
|
||||||
|
requestType: LISTOLD,
|
||||||
|
age: age,
|
||||||
|
env: env,
|
||||||
|
responseChannel: responseChannel,
|
||||||
|
}
|
||||||
|
resp := <-responseChannel
|
||||||
|
return resp.objects, resp.error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fsc *FunctionServiceCache) Log() {
|
||||||
|
log.Printf("--- FunctionService Cache Contents")
|
||||||
|
responseChannel := make(chan *fscResponse)
|
||||||
|
fsc.requestChannel <- &fscRequest{
|
||||||
|
requestType: LOG,
|
||||||
|
responseChannel: responseChannel,
|
||||||
|
}
|
||||||
|
<-responseChannel
|
||||||
|
log.Printf("--- FunctionService Cache Contents End")
|
||||||
|
}
|
||||||
+35
-19
@@ -1,14 +1,15 @@
|
|||||||
package poolmgr
|
package fscache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/client-go/pkg/api"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFunctionServiceCache(t *testing.T) {
|
func TestFunctionServiceCache(t *testing.T) {
|
||||||
@@ -17,16 +18,31 @@ func TestFunctionServiceCache(t *testing.T) {
|
|||||||
log.Panicf("error creating cache")
|
log.Panicf("error creating cache")
|
||||||
}
|
}
|
||||||
|
|
||||||
var fsvc *funcSvc
|
var fsvc *FuncSvc
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
fsvc = &funcSvc{
|
objects := []api.ObjectReference{
|
||||||
function: &api.ObjectMeta{
|
{
|
||||||
|
Kind: "pod",
|
||||||
|
Name: "xxx",
|
||||||
|
APIVersion: "v1",
|
||||||
|
Namespace: "fission-function",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Kind: "pod",
|
||||||
|
Name: "xxx2",
|
||||||
|
APIVersion: "v1",
|
||||||
|
Namespace: "fission-function",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fsvc = &FuncSvc{
|
||||||
|
Function: &metav1.ObjectMeta{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
UID: "1212",
|
UID: "1212",
|
||||||
},
|
},
|
||||||
environment: &tpr.Environment{
|
Environment: &crd.Environment{
|
||||||
Metadata: api.ObjectMeta{
|
Metadata: metav1.ObjectMeta{
|
||||||
Name: "foo-env",
|
Name: "foo-env",
|
||||||
UID: "2323",
|
UID: "2323",
|
||||||
},
|
},
|
||||||
@@ -38,10 +54,10 @@ func TestFunctionServiceCache(t *testing.T) {
|
|||||||
Builder: fission.Builder{},
|
Builder: fission.Builder{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
address: "xxx",
|
Address: "xxx",
|
||||||
podName: "yyy",
|
KubernetesObjects: objects,
|
||||||
ctime: now,
|
Ctime: now,
|
||||||
atime: now,
|
Atime: now,
|
||||||
}
|
}
|
||||||
err, _ := fsc.Add(*fsvc)
|
err, _ := fsc.Add(*fsvc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -49,25 +65,25 @@ func TestFunctionServiceCache(t *testing.T) {
|
|||||||
log.Panicf("Failed to add fsvc: %v", err)
|
log.Panicf("Failed to add fsvc: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := fsc.GetByFunction(fsvc.function)
|
f, err := fsc.GetByFunction(fsvc.Function)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fsc.Log()
|
fsc.Log()
|
||||||
log.Panicf("Failed to get fsvc: %v", err)
|
log.Panicf("Failed to get fsvc: %v", err)
|
||||||
}
|
}
|
||||||
fsvc.atime = f.atime
|
fsvc.Atime = f.Atime
|
||||||
fsvc.ctime = f.ctime
|
fsvc.Ctime = f.Ctime
|
||||||
if *f != *fsvc {
|
if f.Address != fsvc.Address {
|
||||||
fsc.Log()
|
fsc.Log()
|
||||||
log.Panicf("Incorrect fsvc \n(expected: %#v)\n (found: %#v)", fsvc, f)
|
log.Panicf("Incorrect fsvc \n(expected: %#v)\n (found: %#v)", fsvc, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = fsc.TouchByAddress(fsvc.address)
|
err = fsc.TouchByAddress(fsvc.Address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fsc.Log()
|
fsc.Log()
|
||||||
log.Panicf("Failed to touch fsvc: %v", err)
|
log.Panicf("Failed to touch fsvc: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
deleted, err := fsc.DeleteByPod(fsvc.podName, 0)
|
deleted, err := fsc.DeleteOld(fsvc, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fsc.Log()
|
fsc.Log()
|
||||||
log.Panicf("Failed to delete fsvc: %v", err)
|
log.Panicf("Failed to delete fsvc: %v", err)
|
||||||
@@ -77,7 +93,7 @@ func TestFunctionServiceCache(t *testing.T) {
|
|||||||
log.Panicf("Did not delete fsvc")
|
log.Panicf("Did not delete fsvc")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = fsc.GetByFunction(fsvc.function)
|
_, err = fsc.GetByFunction(fsvc.Function)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
fsc.Log()
|
fsc.Log()
|
||||||
log.Panicf("found fsvc while expecting empty cache: %v", err)
|
log.Panicf("found fsvc while expecting empty cache: %v", err)
|
||||||
@@ -20,13 +20,13 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/kubernetes"
|
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
"k8s.io/client-go/kubernetes"
|
||||||
)
|
)
|
||||||
|
|
||||||
// cleanupOldPoolmgrResources looks for resources created by an old
|
// cleanupOldPoolmgrResources looks for resources created by an old
|
||||||
// poolmgr instance and cleans them up.
|
// poolmgr instance and cleans them up.
|
||||||
func cleanupOldPoolmgrResources(client *kubernetes.Clientset, namespace string, instanceId string) {
|
func CleanupOldPoolmgrResources(client *kubernetes.Clientset, namespace string, instanceId string) {
|
||||||
go func() {
|
go func() {
|
||||||
err := cleanup(client, namespace, instanceId)
|
err := cleanup(client, namespace, instanceId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -74,7 +74,7 @@ func cleanup(client *kubernetes.Clientset, namespace string, instanceId string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func cleanupDeployments(client *kubernetes.Clientset, namespace string, instanceId string) error {
|
func cleanupDeployments(client *kubernetes.Clientset, namespace string, instanceId string) error {
|
||||||
deploymentList, err := client.Extensions().Deployments(namespace).List(api.ListOptions{})
|
deploymentList, err := client.ExtensionsV1beta1().Deployments(namespace).List(meta_v1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ func cleanupDeployments(client *kubernetes.Clientset, namespace string, instance
|
|||||||
id, ok := dep.ObjectMeta.Labels[POOLMGR_INSTANCEID_LABEL]
|
id, ok := dep.ObjectMeta.Labels[POOLMGR_INSTANCEID_LABEL]
|
||||||
if ok && id != instanceId {
|
if ok && id != instanceId {
|
||||||
log.Printf("Cleaning up deployment %v", dep.ObjectMeta.Name)
|
log.Printf("Cleaning up deployment %v", dep.ObjectMeta.Name)
|
||||||
err := client.Extensions().Deployments(namespace).Delete(dep.ObjectMeta.Name, nil)
|
err := client.ExtensionsV1beta1().Deployments(namespace).Delete(dep.ObjectMeta.Name, nil)
|
||||||
logErr("cleaning up deployment", err)
|
logErr("cleaning up deployment", err)
|
||||||
// ignore err
|
// ignore err
|
||||||
}
|
}
|
||||||
@@ -91,7 +91,7 @@ func cleanupDeployments(client *kubernetes.Clientset, namespace string, instance
|
|||||||
}
|
}
|
||||||
|
|
||||||
func cleanupReplicaSets(client *kubernetes.Clientset, namespace string, instanceId string) error {
|
func cleanupReplicaSets(client *kubernetes.Clientset, namespace string, instanceId string) error {
|
||||||
rsList, err := client.Extensions().ReplicaSets(namespace).List(api.ListOptions{})
|
rsList, err := client.ExtensionsV1beta1().ReplicaSets(namespace).List(meta_v1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ func cleanupReplicaSets(client *kubernetes.Clientset, namespace string, instance
|
|||||||
id, ok := rs.ObjectMeta.Labels[POOLMGR_INSTANCEID_LABEL]
|
id, ok := rs.ObjectMeta.Labels[POOLMGR_INSTANCEID_LABEL]
|
||||||
if ok && id != instanceId {
|
if ok && id != instanceId {
|
||||||
log.Printf("Cleaning up replicaset %v", rs.ObjectMeta.Name)
|
log.Printf("Cleaning up replicaset %v", rs.ObjectMeta.Name)
|
||||||
err := client.Extensions().ReplicaSets(namespace).Delete(rs.ObjectMeta.Name, nil)
|
err := client.ExtensionsV1beta1().ReplicaSets(namespace).Delete(rs.ObjectMeta.Name, nil)
|
||||||
logErr("cleaning up replicaset", err)
|
logErr("cleaning up replicaset", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,7 +107,7 @@ func cleanupReplicaSets(client *kubernetes.Clientset, namespace string, instance
|
|||||||
}
|
}
|
||||||
|
|
||||||
func cleanupPods(client *kubernetes.Clientset, namespace string, instanceId string) error {
|
func cleanupPods(client *kubernetes.Clientset, namespace string, instanceId string) error {
|
||||||
podList, err := client.Core().Pods(namespace).List(api.ListOptions{})
|
podList, err := client.CoreV1().Pods(namespace).List(meta_v1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -115,7 +115,7 @@ func cleanupPods(client *kubernetes.Clientset, namespace string, instanceId stri
|
|||||||
id, ok := pod.ObjectMeta.Labels[POOLMGR_INSTANCEID_LABEL]
|
id, ok := pod.ObjectMeta.Labels[POOLMGR_INSTANCEID_LABEL]
|
||||||
if ok && id != instanceId {
|
if ok && id != instanceId {
|
||||||
log.Printf("Cleaning up pod %v", pod.ObjectMeta.Name)
|
log.Printf("Cleaning up pod %v", pod.ObjectMeta.Name)
|
||||||
err := client.Core().Pods(namespace).Delete(pod.ObjectMeta.Name, nil)
|
err := client.CoreV1().Pods(namespace).Delete(pod.ObjectMeta.Name, nil)
|
||||||
logErr("cleaning up pod", err)
|
logErr("cleaning up pod", err)
|
||||||
// ignore err
|
// ignore err
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ func cleanupPods(client *kubernetes.Clientset, namespace string, instanceId stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
func cleanupServices(client *kubernetes.Clientset, namespace string, instanceId string) error {
|
func cleanupServices(client *kubernetes.Clientset, namespace string, instanceId string) error {
|
||||||
svcList, err := client.Core().Services(namespace).List(api.ListOptions{})
|
svcList, err := client.CoreV1().Services(namespace).List(meta_v1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -132,7 +132,7 @@ func cleanupServices(client *kubernetes.Clientset, namespace string, instanceId
|
|||||||
id, ok := svc.ObjectMeta.Labels[POOLMGR_INSTANCEID_LABEL]
|
id, ok := svc.ObjectMeta.Labels[POOLMGR_INSTANCEID_LABEL]
|
||||||
if ok && id != instanceId {
|
if ok && id != instanceId {
|
||||||
log.Printf("Cleaning up svc %v", svc.ObjectMeta.Name)
|
log.Printf("Cleaning up svc %v", svc.ObjectMeta.Name)
|
||||||
err := client.Core().Services(namespace).Delete(svc.ObjectMeta.Name, nil)
|
err := client.CoreV1().Services(namespace).Delete(svc.ObjectMeta.Name, nil)
|
||||||
logErr("cleaning up svc", err)
|
logErr("cleaning up svc", err)
|
||||||
// ignore err
|
// ignore err
|
||||||
}
|
}
|
||||||
@@ -32,18 +32,19 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/dchest/uniuri"
|
"github.com/dchest/uniuri"
|
||||||
"k8s.io/client-go/1.5/kubernetes"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/client-go/1.5/pkg/api/v1"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
"k8s.io/client-go/1.5/pkg/apis/extensions/v1beta1"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/1.5/pkg/labels"
|
"k8s.io/client-go/pkg/api"
|
||||||
"k8s.io/client-go/1.5/pkg/util/intstr"
|
apiv1 "k8s.io/client-go/pkg/api/v1"
|
||||||
|
"k8s.io/client-go/pkg/apis/extensions/v1beta1"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
|
"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"
|
"github.com/fission/fission/executor/fscache"
|
||||||
"github.com/fission/fission/tpr"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const POOLMGR_INSTANCEID_LABEL string = "poolmgrInstanceId"
|
const POOLMGR_INSTANCEID_LABEL string = "poolmgrInstanceId"
|
||||||
@@ -51,24 +52,24 @@ const POD_PHASE_RUNNING string = "Running"
|
|||||||
|
|
||||||
type (
|
type (
|
||||||
GenericPool struct {
|
GenericPool struct {
|
||||||
env *tpr.Environment
|
env *crd.Environment
|
||||||
replicas int32 // num idle pods
|
replicas int32 // num idle pods
|
||||||
deployment *v1beta1.Deployment // kubernetes deployment
|
deployment *v1beta1.Deployment // kubernetes deployment
|
||||||
namespace string // namespace to keep our resources
|
namespace string // namespace to keep our resources
|
||||||
podReadyTimeout time.Duration // timeout for generic pods to become ready
|
podReadyTimeout time.Duration // timeout for generic pods to become ready
|
||||||
idlePodReapTime time.Duration // pods unused for idlePodReapTime are deleted
|
idlePodReapTime time.Duration // pods unused for idlePodReapTime are deleted
|
||||||
fsCache *functionServiceCache // cache funcSvc's by function, address and podname
|
fsCache *fscache.FunctionServiceCache // cache funcSvc's by function, address and podname
|
||||||
useSvc bool // create k8s service for specialized pods
|
useSvc bool // create k8s service for specialized pods
|
||||||
poolInstanceId string // small random string to uniquify pod names
|
poolInstanceId string // small random string to uniquify pod names
|
||||||
fetcherImage string
|
fetcherImage string
|
||||||
fetcherImagePullPolicy v1.PullPolicy
|
fetcherImagePullPolicy apiv1.PullPolicy
|
||||||
runtimeImagePullPolicy v1.PullPolicy // pull policy for generic pool to created env deployment
|
runtimeImagePullPolicy apiv1.PullPolicy // pull policy for generic pool to created env deployment
|
||||||
kubernetesClient *kubernetes.Clientset
|
kubernetesClient *kubernetes.Clientset
|
||||||
fissionClient *tpr.FissionClient
|
fissionClient *crd.FissionClient
|
||||||
instanceId string // poolmgr instance id
|
instanceId string // poolmgr instance id
|
||||||
labelsForPool map[string]string
|
labelsForPool map[string]string
|
||||||
requestChannel chan *choosePodRequest
|
requestChannel chan *choosePodRequest
|
||||||
sharedMountPath string
|
sharedMountPath string // used by generic pool when creating env deployment to specify the share volume path for fetcher & env
|
||||||
}
|
}
|
||||||
|
|
||||||
// serialize the choosing of pods so that choices don't conflict
|
// serialize the choosing of pods so that choices don't conflict
|
||||||
@@ -77,29 +78,29 @@ type (
|
|||||||
responseChannel chan *choosePodResponse
|
responseChannel chan *choosePodResponse
|
||||||
}
|
}
|
||||||
choosePodResponse struct {
|
choosePodResponse struct {
|
||||||
pod *v1.Pod
|
pod *apiv1.Pod
|
||||||
error
|
error
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func getImagePullPolicy(policy string) v1.PullPolicy {
|
func getImagePullPolicy(policy string) apiv1.PullPolicy {
|
||||||
switch policy {
|
switch policy {
|
||||||
case "Always":
|
case "Always":
|
||||||
return v1.PullAlways
|
return apiv1.PullAlways
|
||||||
case "Never":
|
case "Never":
|
||||||
return v1.PullNever
|
return apiv1.PullNever
|
||||||
default:
|
default:
|
||||||
return v1.PullIfNotPresent
|
return apiv1.PullIfNotPresent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeGenericPool(
|
func MakeGenericPool(
|
||||||
fissionClient *tpr.FissionClient,
|
fissionClient *crd.FissionClient,
|
||||||
kubernetesClient *kubernetes.Clientset,
|
kubernetesClient *kubernetes.Clientset,
|
||||||
env *tpr.Environment,
|
env *crd.Environment,
|
||||||
initialReplicas int32,
|
initialReplicas int32,
|
||||||
namespace string,
|
namespace string,
|
||||||
fsCache *functionServiceCache,
|
fsCache *fscache.FunctionServiceCache,
|
||||||
instanceId string) (*GenericPool, error) {
|
instanceId string) (*GenericPool, error) {
|
||||||
|
|
||||||
log.Printf("Creating pool for environment %v", env.Metadata)
|
log.Printf("Creating pool for environment %v", env.Metadata)
|
||||||
@@ -133,7 +134,7 @@ func MakeGenericPool(
|
|||||||
instanceId: instanceId,
|
instanceId: instanceId,
|
||||||
fetcherImage: fetcherImage,
|
fetcherImage: fetcherImage,
|
||||||
useSvc: false, // defaults off -- svc takes a second or more to become routable, slowing cold start
|
useSvc: false, // defaults off -- svc takes a second or more to become routable, slowing cold start
|
||||||
sharedMountPath: "/userfunc", // used by generic pool when creating env deployment to specify the share volume path for fetcher & env
|
sharedMountPath: "/userfunc", // change this may break v1 compatibility, since most of the v1 environments have hard-coded "/userfunc" in loading path
|
||||||
}
|
}
|
||||||
|
|
||||||
gp.runtimeImagePullPolicy = getImagePullPolicy(runtimeImagePullPolicy)
|
gp.runtimeImagePullPolicy = getImagePullPolicy(runtimeImagePullPolicy)
|
||||||
@@ -182,7 +183,7 @@ func (gp *GenericPool) choosePodService() {
|
|||||||
|
|
||||||
// choosePod picks a ready pod from the pool and relabels it, waiting if necessary.
|
// choosePod picks a ready pod from the pool and relabels it, waiting if necessary.
|
||||||
// returns the pod API object.
|
// returns the pod API object.
|
||||||
func (gp *GenericPool) choosePod(newLabels map[string]string) (*v1.Pod, error) {
|
func (gp *GenericPool) choosePod(newLabels map[string]string) (*apiv1.Pod, error) {
|
||||||
req := &choosePodRequest{
|
req := &choosePodRequest{
|
||||||
newLabels: newLabels,
|
newLabels: newLabels,
|
||||||
responseChannel: make(chan *choosePodResponse),
|
responseChannel: make(chan *choosePodResponse),
|
||||||
@@ -193,7 +194,7 @@ func (gp *GenericPool) choosePod(newLabels map[string]string) (*v1.Pod, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// _choosePod is called serially by choosePodService
|
// _choosePod is called serially by choosePodService
|
||||||
func (gp *GenericPool) _choosePod(newLabels map[string]string) (*v1.Pod, error) {
|
func (gp *GenericPool) _choosePod(newLabels map[string]string) (*apiv1.Pod, error) {
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
for {
|
for {
|
||||||
// Retries took too long, error out.
|
// Retries took too long, error out.
|
||||||
@@ -203,14 +204,15 @@ func (gp *GenericPool) _choosePod(newLabels map[string]string) (*v1.Pod, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get pods; filter the ones that are ready
|
// Get pods; filter the ones that are ready
|
||||||
podList, err := gp.kubernetesClient.Core().Pods(gp.namespace).List(
|
podList, err := gp.kubernetesClient.CoreV1().Pods(gp.namespace).List(
|
||||||
api.ListOptions{
|
metav1.ListOptions{
|
||||||
LabelSelector: labels.Set(gp.deployment.Spec.Selector.MatchLabels).AsSelector(),
|
LabelSelector: labels.Set(
|
||||||
|
gp.deployment.Spec.Selector.MatchLabels).AsSelector().String(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
readyPods := make([]*v1.Pod, 0, len(podList.Items))
|
readyPods := make([]*apiv1.Pod, 0, len(podList.Items))
|
||||||
for i := range podList.Items {
|
for i := range podList.Items {
|
||||||
pod := podList.Items[i]
|
pod := podList.Items[i]
|
||||||
|
|
||||||
@@ -252,7 +254,7 @@ func (gp *GenericPool) _choosePod(newLabels map[string]string) (*v1.Pod, error)
|
|||||||
// retry.
|
// retry.
|
||||||
chosenPod.ObjectMeta.Labels = newLabels
|
chosenPod.ObjectMeta.Labels = newLabels
|
||||||
log.Printf("relabeling pod: [%v]", chosenPod.ObjectMeta.Name)
|
log.Printf("relabeling pod: [%v]", chosenPod.ObjectMeta.Name)
|
||||||
_, err = gp.kubernetesClient.Core().Pods(gp.namespace).Update(chosenPod)
|
_, err = gp.kubernetesClient.CoreV1().Pods(gp.namespace).Update(chosenPod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("failed to relabel pod [%v]: %v", chosenPod.ObjectMeta.Name, err)
|
log.Printf("failed to relabel pod [%v]: %v", chosenPod.ObjectMeta.Name, err)
|
||||||
continue
|
continue
|
||||||
@@ -263,7 +265,7 @@ func (gp *GenericPool) _choosePod(newLabels map[string]string) (*v1.Pod, error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gp *GenericPool) labelsForFunction(metadata *api.ObjectMeta) map[string]string {
|
func (gp *GenericPool) labelsForFunction(metadata *metav1.ObjectMeta) map[string]string {
|
||||||
return map[string]string{
|
return map[string]string{
|
||||||
"functionName": metadata.Name,
|
"functionName": metadata.Name,
|
||||||
"functionUid": string(metadata.UID),
|
"functionUid": string(metadata.UID),
|
||||||
@@ -279,10 +281,15 @@ func (gp *GenericPool) scheduleDeletePod(name string) {
|
|||||||
// aggregation and storage will help.)
|
// aggregation and storage will help.)
|
||||||
log.Printf("Error in pod '%v', scheduling cleanup", name)
|
log.Printf("Error in pod '%v', scheduling cleanup", name)
|
||||||
time.Sleep(5 * time.Minute)
|
time.Sleep(5 * time.Minute)
|
||||||
gp.kubernetesClient.Core().Pods(gp.namespace).Delete(name, nil)
|
gp.kubernetesClient.CoreV1().Pods(gp.namespace).Delete(name, nil)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsIPv6(podIP string) bool {
|
||||||
|
ip := net.ParseIP(podIP)
|
||||||
|
return ip != nil && strings.Contains(podIP, ":")
|
||||||
|
}
|
||||||
|
|
||||||
func (gp *GenericPool) getFetcherUrl(podIP string) string {
|
func (gp *GenericPool) getFetcherUrl(podIP string) string {
|
||||||
testUrl := os.Getenv("TEST_FETCHER_URL")
|
testUrl := os.Getenv("TEST_FETCHER_URL")
|
||||||
if len(testUrl) != 0 {
|
if len(testUrl) != 0 {
|
||||||
@@ -292,24 +299,41 @@ func (gp *GenericPool) getFetcherUrl(podIP string) string {
|
|||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
return testUrl
|
return testUrl
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("http://%v:8000/", podIP)
|
isv6 := IsIPv6(podIP)
|
||||||
|
var baseUrl string
|
||||||
|
if isv6 == false {
|
||||||
|
baseUrl = fmt.Sprintf("http://%v:8000/", podIP)
|
||||||
|
} else if isv6 == true { // We use bracket if the IP is in IPv6.
|
||||||
|
baseUrl = fmt.Sprintf("http://[%v]:8000/", podIP)
|
||||||
|
}
|
||||||
|
return baseUrl
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gp *GenericPool) getSpecializeUrl(podIP string, version int) string {
|
func (gp *GenericPool) getSpecializeUrl(podIP string, version int) string {
|
||||||
u := os.Getenv("TEST_SPECIALIZE_URL")
|
u := os.Getenv("TEST_SPECIALIZE_URL")
|
||||||
|
isv6 := IsIPv6(podIP)
|
||||||
|
var baseUrl string
|
||||||
if len(u) != 0 {
|
if len(u) != 0 {
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
if version == 1 {
|
if isv6 == false {
|
||||||
return fmt.Sprintf("http://%v:8888/specialize", podIP)
|
baseUrl = fmt.Sprintf("http://%v:8888", podIP)
|
||||||
|
} else if isv6 == true { // We use bracket if the IP is in IPv6.
|
||||||
|
baseUrl = fmt.Sprintf("http://[%v]:8888", podIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
if version == 1 {
|
||||||
|
return fmt.Sprintf("%v/specialize", baseUrl)
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%v/v%v/specialize", baseUrl, version)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("http://%v:8888/v%v/specialize", podIP, version)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// specializePod chooses a pod, copies the required user-defined function to that pod
|
// specializePod chooses a pod, copies the required user-defined function to that pod
|
||||||
// (via fetcher), and calls the function-run container to load it, resulting in a
|
// (via fetcher), and calls the function-run container to load it, resulting in a
|
||||||
// specialized pod.
|
// specialized pod.
|
||||||
func (gp *GenericPool) specializePod(pod *v1.Pod, metadata *api.ObjectMeta) error {
|
func (gp *GenericPool) specializePod(pod *apiv1.Pod, metadata *metav1.ObjectMeta) error {
|
||||||
// for fetcher we don't need to create a service, just talk to the pod directly
|
// for fetcher we don't need to create a service, just talk to the pod directly
|
||||||
podIP := pod.Status.PodIP
|
podIP := pod.Status.PodIP
|
||||||
if len(podIP) == 0 {
|
if len(podIP) == 0 {
|
||||||
@@ -327,23 +351,26 @@ func (gp *GenericPool) specializePod(pod *v1.Pod, metadata *api.ObjectMeta) erro
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for backward compatibility, since most v1 env
|
||||||
|
// still try to load user function from hard coded
|
||||||
|
// path /userfunc/user
|
||||||
targetFilename := "user"
|
targetFilename := "user"
|
||||||
|
if gp.env.Spec.Version == 2 {
|
||||||
|
targetFilename = string(fn.Metadata.UID)
|
||||||
|
}
|
||||||
|
|
||||||
err = fetcherClient.MakeClient(fetcherUrl).Fetch(&fetcher.FetchRequest{
|
err = fetcherClient.MakeClient(fetcherUrl).Fetch(&fetcher.FetchRequest{
|
||||||
FetchType: fetcher.FETCH_DEPLOYMENT,
|
FetchType: fetcher.FETCH_DEPLOYMENT,
|
||||||
Package: api.ObjectMeta{
|
Package: metav1.ObjectMeta{
|
||||||
Namespace: fn.Spec.Package.PackageRef.Namespace,
|
Namespace: fn.Spec.Package.PackageRef.Namespace,
|
||||||
Name: fn.Spec.Package.PackageRef.Name,
|
Name: fn.Spec.Package.PackageRef.Name,
|
||||||
},
|
},
|
||||||
Filename: targetFilename, // XXX use function id instead
|
Filename: targetFilename,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
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)
|
||||||
|
|
||||||
@@ -406,35 +433,35 @@ func (gp *GenericPool) createPool() error {
|
|||||||
gp.env.Metadata.Name, gp.env.Metadata.UID, strings.ToLower(gp.poolInstanceId))
|
gp.env.Metadata.Name, gp.env.Metadata.UID, strings.ToLower(gp.poolInstanceId))
|
||||||
|
|
||||||
deployment := &v1beta1.Deployment{
|
deployment := &v1beta1.Deployment{
|
||||||
ObjectMeta: v1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: poolDeploymentName,
|
Name: poolDeploymentName,
|
||||||
Labels: gp.labelsForPool,
|
Labels: gp.labelsForPool,
|
||||||
},
|
},
|
||||||
Spec: v1beta1.DeploymentSpec{
|
Spec: v1beta1.DeploymentSpec{
|
||||||
Replicas: &gp.replicas,
|
Replicas: &gp.replicas,
|
||||||
Selector: &v1beta1.LabelSelector{
|
Selector: &metav1.LabelSelector{
|
||||||
MatchLabels: gp.labelsForPool,
|
MatchLabels: gp.labelsForPool,
|
||||||
},
|
},
|
||||||
Template: v1.PodTemplateSpec{
|
Template: apiv1.PodTemplateSpec{
|
||||||
ObjectMeta: v1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Labels: gp.labelsForPool,
|
Labels: gp.labelsForPool,
|
||||||
},
|
},
|
||||||
Spec: v1.PodSpec{
|
Spec: apiv1.PodSpec{
|
||||||
Volumes: []v1.Volume{
|
Volumes: []apiv1.Volume{
|
||||||
{
|
{
|
||||||
Name: "userfunc",
|
Name: "userfunc",
|
||||||
VolumeSource: v1.VolumeSource{
|
VolumeSource: apiv1.VolumeSource{
|
||||||
EmptyDir: &v1.EmptyDirVolumeSource{},
|
EmptyDir: &apiv1.EmptyDirVolumeSource{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Containers: []v1.Container{
|
Containers: []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,
|
||||||
TerminationMessagePath: "/dev/termination-log",
|
TerminationMessagePath: "/dev/termination-log",
|
||||||
VolumeMounts: []v1.VolumeMount{
|
VolumeMounts: []apiv1.VolumeMount{
|
||||||
{
|
{
|
||||||
Name: "userfunc",
|
Name: "userfunc",
|
||||||
MountPath: gp.sharedMountPath,
|
MountPath: gp.sharedMountPath,
|
||||||
@@ -446,7 +473,7 @@ func (gp *GenericPool) createPool() error {
|
|||||||
Image: gp.fetcherImage,
|
Image: gp.fetcherImage,
|
||||||
ImagePullPolicy: gp.fetcherImagePullPolicy,
|
ImagePullPolicy: gp.fetcherImagePullPolicy,
|
||||||
TerminationMessagePath: "/dev/termination-log",
|
TerminationMessagePath: "/dev/termination-log",
|
||||||
VolumeMounts: []v1.VolumeMount{
|
VolumeMounts: []apiv1.VolumeMount{
|
||||||
{
|
{
|
||||||
Name: "userfunc",
|
Name: "userfunc",
|
||||||
MountPath: gp.sharedMountPath,
|
MountPath: gp.sharedMountPath,
|
||||||
@@ -460,7 +487,7 @@ func (gp *GenericPool) createPool() error {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
depl, err := gp.kubernetesClient.Extensions().Deployments(gp.namespace).Create(deployment)
|
depl, err := gp.kubernetesClient.ExtensionsV1beta1().Deployments(gp.namespace).Create(deployment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -472,7 +499,8 @@ func (gp *GenericPool) waitForReadyPod() error {
|
|||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
for {
|
for {
|
||||||
// TODO: for now we just poll; use a watch instead
|
// TODO: for now we just poll; use a watch instead
|
||||||
depl, err := gp.kubernetesClient.Extensions().Deployments(gp.namespace).Get(gp.deployment.ObjectMeta.Name)
|
depl, err := gp.kubernetesClient.ExtensionsV1beta1().Deployments(gp.namespace).Get(
|
||||||
|
gp.deployment.ObjectMeta.Name, metav1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("err: %v", err)
|
log.Printf("err: %v", err)
|
||||||
return err
|
return err
|
||||||
@@ -489,16 +517,16 @@ func (gp *GenericPool) waitForReadyPod() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gp *GenericPool) createSvc(name string, labels map[string]string) (*v1.Service, error) {
|
func (gp *GenericPool) createSvc(name string, labels map[string]string) (*apiv1.Service, error) {
|
||||||
service := v1.Service{
|
service := apiv1.Service{
|
||||||
ObjectMeta: v1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
},
|
},
|
||||||
Spec: v1.ServiceSpec{
|
Spec: apiv1.ServiceSpec{
|
||||||
Type: v1.ServiceTypeClusterIP,
|
Type: apiv1.ServiceTypeClusterIP,
|
||||||
Ports: []v1.ServicePort{
|
Ports: []apiv1.ServicePort{
|
||||||
{
|
{
|
||||||
Protocol: v1.ProtocolTCP,
|
Protocol: apiv1.ProtocolTCP,
|
||||||
Port: 80,
|
Port: 80,
|
||||||
TargetPort: intstr.FromInt(8888),
|
TargetPort: intstr.FromInt(8888),
|
||||||
},
|
},
|
||||||
@@ -506,11 +534,11 @@ func (gp *GenericPool) createSvc(name string, labels map[string]string) (*v1.Ser
|
|||||||
Selector: labels,
|
Selector: labels,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
svc, err := gp.kubernetesClient.Core().Services(gp.namespace).Create(&service)
|
svc, err := gp.kubernetesClient.CoreV1().Services(gp.namespace).Create(&service)
|
||||||
return svc, err
|
return svc, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gp *GenericPool) GetFuncSvc(m *api.ObjectMeta) (*funcSvc, error) {
|
func (gp *GenericPool) GetFuncSvc(m *metav1.ObjectMeta) (*fscache.FuncSvc, error) {
|
||||||
|
|
||||||
log.Printf("[%v] Choosing pod from pool", m.Name)
|
log.Printf("[%v] Choosing pod from pool", m.Name)
|
||||||
newLabels := gp.labelsForFunction(m)
|
newLabels := gp.labelsForFunction(m)
|
||||||
@@ -552,66 +580,69 @@ func (gp *GenericPool) GetFuncSvc(m *api.ObjectMeta) (*funcSvc, error) {
|
|||||||
svcHost = fmt.Sprintf("%v:8888", pod.Status.PodIP)
|
svcHost = fmt.Sprintf("%v:8888", pod.Status.PodIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
fsvc := &funcSvc{
|
kubeObjRefs := []api.ObjectReference{
|
||||||
function: m,
|
{
|
||||||
environment: gp.env,
|
Kind: pod.TypeMeta.Kind,
|
||||||
address: svcHost,
|
Name: pod.ObjectMeta.Name,
|
||||||
podName: pod.ObjectMeta.Name,
|
APIVersion: pod.TypeMeta.APIVersion,
|
||||||
ctime: time.Now(),
|
Namespace: pod.ObjectMeta.Namespace,
|
||||||
atime: time.Now(),
|
ResourceVersion: pod.ObjectMeta.ResourceVersion,
|
||||||
|
UID: pod.ObjectMeta.UID,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err, existingFsvc := gp.fsCache.Add(*fsvc)
|
fsvc := &fscache.FuncSvc{
|
||||||
|
Function: m,
|
||||||
|
Environment: gp.env,
|
||||||
|
Address: svcHost,
|
||||||
|
KubernetesObjects: kubeObjRefs,
|
||||||
|
Backend: fscache.POOLMGR,
|
||||||
|
Ctime: time.Now(),
|
||||||
|
Atime: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
err, _ = gp.fsCache.Add(*fsvc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if fe, ok := err.(fission.Error); ok {
|
|
||||||
if fe.Code == fission.ErrorNameExists {
|
|
||||||
// Some other thread beat us to it -- return the other thread's fsvc and clean up
|
|
||||||
// our own.
|
|
||||||
log.Printf("func svc already exists: %v", existingFsvc.podName)
|
|
||||||
go func() {
|
|
||||||
gp.kubernetesClient.Core().Pods(gp.namespace).Delete(fsvc.podName, nil)
|
|
||||||
}()
|
|
||||||
return existingFsvc, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return fsvc, nil
|
return fsvc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gp *GenericPool) CleanupFunctionService(podName string) error {
|
func (gp *GenericPool) CleanupFunctionService(obj *fscache.FuncSvc) error {
|
||||||
// remove ourselves from fsCache (only if we're still old)
|
// remove ourselves from fsCache (only if we're still old)
|
||||||
deleted, err := gp.fsCache.DeleteByPod(podName, gp.idlePodReapTime)
|
deleted, err := gp.fsCache.DeleteOld(obj, gp.idlePodReapTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !deleted {
|
if !deleted {
|
||||||
log.Printf("Not deleting %v, in use", podName)
|
log.Printf("Not deleting %v, in use", obj.Function)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
pod, err := gp.kubernetesClient.Core().Pods(gp.namespace).Get(podName)
|
for _, kubeobj := range obj.KubernetesObjects {
|
||||||
if err != nil {
|
pod, err := gp.kubernetesClient.CoreV1().Pods(gp.namespace).Get(kubeobj.Name, metav1.GetOptions{})
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
loggerUrl := fmt.Sprintf("http://%s:1234/v1/log/%s", pod.Spec.NodeName, pod.Name)
|
loggerUrl := fmt.Sprintf("http://%s:1234/v1/log/%s", pod.Spec.NodeName, pod.Name)
|
||||||
req, err := http.NewRequest("DELETE", loggerUrl, nil)
|
req, err := http.NewRequest("DELETE", loggerUrl, nil)
|
||||||
resp, err := http.DefaultClient.Do(req)
|
resp, err := http.DefaultClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error from %s daemonset logger: %v", pod.Spec.NodeName, err)
|
log.Printf("Error from %s daemonset logger: %v", pod.Spec.NodeName, err)
|
||||||
} else {
|
} else {
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
log.Printf("Received not http 200(OK) status from %s daemonset logger: %s", pod.Spec.NodeName, resp.Status)
|
log.Printf("Received not http 200(OK) status from %s daemonset logger: %s", pod.Spec.NodeName, resp.Status)
|
||||||
|
}
|
||||||
|
resp.Body.Close()
|
||||||
}
|
}
|
||||||
resp.Body.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// delete pod
|
// delete pod
|
||||||
err = gp.kubernetesClient.Core().Pods(gp.namespace).Delete(podName, nil)
|
err = gp.kubernetesClient.CoreV1().Pods(gp.namespace).Delete(kubeobj.Name, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -620,16 +651,19 @@ func (gp *GenericPool) CleanupFunctionService(podName string) error {
|
|||||||
func (gp *GenericPool) idlePodReaper() {
|
func (gp *GenericPool) idlePodReaper() {
|
||||||
for {
|
for {
|
||||||
time.Sleep(time.Minute)
|
time.Sleep(time.Minute)
|
||||||
podNames, err := gp.fsCache.ListOld(&gp.env.Metadata, gp.idlePodReapTime)
|
funcSvcs, err := gp.fsCache.ListOld(&gp.env.Metadata, gp.idlePodReapTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error reaping idle pods: %v", err)
|
log.Printf("Error reaping idle pods: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, podName := range podNames {
|
for _, obj := range funcSvcs {
|
||||||
log.Printf("Reaping idle pod '%v'", podName)
|
err := gp.CleanupFunctionService(obj)
|
||||||
err := gp.CleanupFunctionService(podName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error deleting idle pod '%v': %v", podName, err)
|
log.Printf("Error deleting Kubernetes objects for fsvc '%v': %v", obj, err)
|
||||||
|
log.Printf("Object Name| Object Kind | Object Space")
|
||||||
|
for _, kubeobj := range obj.KubernetesObjects {
|
||||||
|
log.Printf("%v | %v | %v", kubeobj.Name, kubeobj.Kind, kubeobj.Namespace)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -638,7 +672,7 @@ func (gp *GenericPool) idlePodReaper() {
|
|||||||
// destroys the pool -- the deployment, replicaset and pods
|
// destroys the pool -- the deployment, replicaset and pods
|
||||||
func (gp *GenericPool) destroy() error {
|
func (gp *GenericPool) destroy() error {
|
||||||
// Destroy deployment
|
// Destroy deployment
|
||||||
err := gp.kubernetesClient.Extensions().Deployments(gp.namespace).Delete(gp.deployment.ObjectMeta.Name, nil)
|
err := gp.kubernetesClient.ExtensionsV1beta1().Deployments(gp.namespace).Delete(gp.deployment.ObjectMeta.Name, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error destroying deployment: %v", err)
|
log.Printf("Error destroying deployment: %v", err)
|
||||||
return err
|
return err
|
||||||
@@ -647,12 +681,12 @@ func (gp *GenericPool) destroy() error {
|
|||||||
// Destroy ReplicaSet. Pre-1.6 K8s versions don't do this
|
// Destroy ReplicaSet. Pre-1.6 K8s versions don't do this
|
||||||
// automatically but post-1.6 K8s will, and may beat us to it,
|
// automatically but post-1.6 K8s will, and may beat us to it,
|
||||||
// so don't error out if we fail.
|
// so don't error out if we fail.
|
||||||
rsList, err := gp.kubernetesClient.Extensions().ReplicaSets(gp.namespace).List(api.ListOptions{
|
rsList, err := gp.kubernetesClient.ExtensionsV1beta1().ReplicaSets(gp.namespace).List(metav1.ListOptions{
|
||||||
LabelSelector: labels.Set(gp.labelsForPool).AsSelector(),
|
LabelSelector: labels.Set(gp.labelsForPool).AsSelector().String(),
|
||||||
})
|
})
|
||||||
if len(rsList.Items) >= 0 {
|
if len(rsList.Items) >= 0 {
|
||||||
for _, rs := range rsList.Items {
|
for _, rs := range rsList.Items {
|
||||||
err = gp.kubernetesClient.Extensions().ReplicaSets(gp.namespace).Delete(rs.ObjectMeta.Name, nil)
|
err = gp.kubernetesClient.ExtensionsV1beta1().ReplicaSets(gp.namespace).Delete(rs.ObjectMeta.Name, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error deleting replicaset, ignoring: %v", err)
|
log.Printf("Error deleting replicaset, ignoring: %v", err)
|
||||||
}
|
}
|
||||||
@@ -660,12 +694,12 @@ func (gp *GenericPool) destroy() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Destroy Pods. See note above.
|
// Destroy Pods. See note above.
|
||||||
podList, err := gp.kubernetesClient.Core().Pods(gp.namespace).List(api.ListOptions{
|
podList, err := gp.kubernetesClient.CoreV1().Pods(gp.namespace).List(metav1.ListOptions{
|
||||||
LabelSelector: labels.Set(gp.labelsForPool).AsSelector(),
|
LabelSelector: labels.Set(gp.labelsForPool).AsSelector().String(),
|
||||||
})
|
})
|
||||||
if len(podList.Items) >= 0 {
|
if len(podList.Items) >= 0 {
|
||||||
for _, pod := range podList.Items {
|
for _, pod := range podList.Items {
|
||||||
err = gp.kubernetesClient.Core().Pods(gp.namespace).Delete(pod.ObjectMeta.Name, nil)
|
err = gp.kubernetesClient.CoreV1().Pods(gp.namespace).Delete(pod.ObjectMeta.Name, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error deleting pod, ignoring: %v", err)
|
log.Printf("Error deleting pod, ignoring: %v", err)
|
||||||
}
|
}
|
||||||
@@ -674,32 +708,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 *v1.Pod, metadata *api.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()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
@@ -20,11 +20,12 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/client-go/1.5/kubernetes"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
|
"github.com/fission/fission/executor/fscache"
|
||||||
)
|
)
|
||||||
|
|
||||||
type requestType int
|
type requestType int
|
||||||
@@ -39,15 +40,16 @@ type (
|
|||||||
pools map[string]*GenericPool
|
pools map[string]*GenericPool
|
||||||
kubernetesClient *kubernetes.Clientset
|
kubernetesClient *kubernetes.Clientset
|
||||||
namespace string
|
namespace string
|
||||||
fissionClient *tpr.FissionClient
|
|
||||||
fsCache *functionServiceCache
|
fissionClient *crd.FissionClient
|
||||||
instanceId string
|
fsCache *fscache.FunctionServiceCache
|
||||||
requestChannel chan *request
|
instanceId string
|
||||||
|
requestChannel chan *request
|
||||||
}
|
}
|
||||||
request struct {
|
request struct {
|
||||||
requestType
|
requestType
|
||||||
env *tpr.Environment
|
env *crd.Environment
|
||||||
envList []tpr.Environment
|
envList []crd.Environment
|
||||||
responseChannel chan *response
|
responseChannel chan *response
|
||||||
}
|
}
|
||||||
response struct {
|
response struct {
|
||||||
@@ -57,11 +59,11 @@ type (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func MakeGenericPoolManager(
|
func MakeGenericPoolManager(
|
||||||
fissionClient *tpr.FissionClient,
|
fissionClient *crd.FissionClient,
|
||||||
kubernetesClient *kubernetes.Clientset,
|
kubernetesClient *kubernetes.Clientset,
|
||||||
fissionNamespace string,
|
fissionNamespace string,
|
||||||
functionNamespace string,
|
functionNamespace string,
|
||||||
fsCache *functionServiceCache,
|
fsCache *fscache.FunctionServiceCache,
|
||||||
instanceId string) *GenericPoolManager {
|
instanceId string) *GenericPoolManager {
|
||||||
|
|
||||||
gpm := &GenericPoolManager{
|
gpm := &GenericPoolManager{
|
||||||
@@ -85,7 +87,7 @@ func (gpm *GenericPoolManager) service() {
|
|||||||
switch req.requestType {
|
switch req.requestType {
|
||||||
case GET_POOL:
|
case GET_POOL:
|
||||||
var err error
|
var err error
|
||||||
pool, ok := gpm.pools[tpr.CacheKey(&req.env.Metadata)]
|
pool, ok := gpm.pools[crd.CacheKey(&req.env.Metadata)]
|
||||||
if !ok {
|
if !ok {
|
||||||
var poolSize int32 = 3 // TODO configurable/autoscalable
|
var poolSize int32 = 3 // TODO configurable/autoscalable
|
||||||
switch req.env.Spec.AllowedFunctionsPerContainer {
|
switch req.env.Spec.AllowedFunctionsPerContainer {
|
||||||
@@ -100,13 +102,13 @@ func (gpm *GenericPoolManager) service() {
|
|||||||
req.responseChannel <- &response{error: err}
|
req.responseChannel <- &response{error: err}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
gpm.pools[tpr.CacheKey(&req.env.Metadata)] = pool
|
gpm.pools[crd.CacheKey(&req.env.Metadata)] = pool
|
||||||
}
|
}
|
||||||
req.responseChannel <- &response{pool: pool}
|
req.responseChannel <- &response{pool: pool}
|
||||||
case CLEANUP_POOLS:
|
case CLEANUP_POOLS:
|
||||||
latestEnvSet := make(map[string]bool)
|
latestEnvSet := make(map[string]bool)
|
||||||
for _, env := range req.envList {
|
for _, env := range req.envList {
|
||||||
latestEnvSet[tpr.CacheKey(&env.Metadata)] = true
|
latestEnvSet[crd.CacheKey(&env.Metadata)] = true
|
||||||
}
|
}
|
||||||
for key, pool := range gpm.pools {
|
for key, pool := range gpm.pools {
|
||||||
_, ok := latestEnvSet[key]
|
_, ok := latestEnvSet[key]
|
||||||
@@ -124,7 +126,7 @@ func (gpm *GenericPoolManager) service() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gpm *GenericPoolManager) GetPool(env *tpr.Environment) (*GenericPool, error) {
|
func (gpm *GenericPoolManager) GetPool(env *crd.Environment) (*GenericPool, error) {
|
||||||
c := make(chan *response)
|
c := make(chan *response)
|
||||||
gpm.requestChannel <- &request{
|
gpm.requestChannel <- &request{
|
||||||
requestType: GET_POOL,
|
requestType: GET_POOL,
|
||||||
@@ -135,7 +137,7 @@ func (gpm *GenericPoolManager) GetPool(env *tpr.Environment) (*GenericPool, erro
|
|||||||
return resp.pool, resp.error
|
return resp.pool, resp.error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gpm *GenericPoolManager) CleanupPools(envs []tpr.Environment) {
|
func (gpm *GenericPoolManager) CleanupPools(envs []crd.Environment) {
|
||||||
gpm.requestChannel <- &request{
|
gpm.requestChannel <- &request{
|
||||||
requestType: CLEANUP_POOLS,
|
requestType: CLEANUP_POOLS,
|
||||||
envList: envs,
|
envList: envs,
|
||||||
@@ -148,7 +150,7 @@ func (gpm *GenericPoolManager) eagerPoolCreator() {
|
|||||||
time.Sleep(pollSleep)
|
time.Sleep(pollSleep)
|
||||||
|
|
||||||
// get list of envs from controller
|
// get list of envs from controller
|
||||||
envs, err := gpm.fissionClient.Environments(api.NamespaceAll).List(api.ListOptions{})
|
envs, err := gpm.fissionClient.Environments(metav1.NamespaceAll).List(metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to get environment list: %v", err)
|
log.Fatalf("Failed to get environment list: %v", err)
|
||||||
}
|
}
|
||||||
+19
-30
@@ -6,12 +6,12 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/docopt/docopt-go"
|
"github.com/docopt/docopt-go"
|
||||||
|
|
||||||
"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/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/router"
|
"github.com/fission/fission/router"
|
||||||
"github.com/fission/fission/storagesvc"
|
"github.com/fission/fission/storagesvc"
|
||||||
"github.com/fission/fission/timer"
|
"github.com/fission/fission/timer"
|
||||||
@@ -22,15 +22,15 @@ func runController(port int) {
|
|||||||
log.Fatalf("Error: Controller exited.")
|
log.Fatalf("Error: Controller exited.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func runRouter(port int, poolmgrUrl string) {
|
func runRouter(port int, executorUrl string) {
|
||||||
router.Start(port, poolmgrUrl)
|
router.Start(port, executorUrl)
|
||||||
log.Fatalf("Error: Router exited.")
|
log.Fatalf("Error: Router exited.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func runPoolmgr(port int, fissionNamespace, functionNamespace string) {
|
func runExecutor(port int, fissionNamespace, functionNamespace string) {
|
||||||
err := poolmgr.StartPoolmgr(fissionNamespace, functionNamespace, port)
|
err := executor.StartExecutor(fissionNamespace, functionNamespace, port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error starting poolmgr: %v", err)
|
log.Fatalf("Error starting executor: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,11 +41,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 {
|
||||||
@@ -94,18 +89,18 @@ func getStringArgWithDefault(arg interface{}, defaultValue string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
usage := `fission-bundle: Package of all fission microservices: controller, router, poolmgr.
|
usage := `fission-bundle: Package of all fission microservices: controller, router, executor.
|
||||||
|
|
||||||
Use it to start one or more of the fission servers:
|
Use it to start one or more of the fission servers:
|
||||||
|
|
||||||
Controller is a stateless API frontend for fission resources.
|
Controller is a stateless API frontend for fission resources.
|
||||||
|
|
||||||
Pool manager maintains a pool of generalized function containers, and
|
Pool manager maintains a pool of generalized function containers, and
|
||||||
specializes them on-demand. Poolmgr must be run from a pod in a
|
specializes them on-demand. Executor must be run from a pod in a
|
||||||
Kubernetes cluster.
|
Kubernetes cluster.
|
||||||
|
|
||||||
Router implements HTTP triggers: it routes to running instances,
|
Router implements HTTP triggers: it routes to running instances,
|
||||||
working with the controller and poolmgr.
|
working with the controller and executor.
|
||||||
|
|
||||||
Kubewatcher implements Kubernetes Watch triggers: it watches
|
Kubewatcher implements Kubernetes Watch triggers: it watches
|
||||||
Kubernetes resources and invokes functions described in the
|
Kubernetes resources and invokes functions described in the
|
||||||
@@ -117,28 +112,26 @@ Use it to start one or more of the fission servers:
|
|||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
fission-bundle --controllerPort=<port>
|
fission-bundle --controllerPort=<port>
|
||||||
fission-bundle --routerPort=<port> [--poolmgrUrl=<url>]
|
fission-bundle --routerPort=<port> [--executorUrl=<url>]
|
||||||
fission-bundle --poolmgrPort=<port> [--namespace=<namespace>] [--fission-namespace=<namespace>]
|
fission-bundle --executorPort=<port> [--namespace=<namespace>] [--fission-namespace=<namespace>]
|
||||||
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:
|
||||||
--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.
|
||||||
--poolmgrPort=<port> Port that the poolmgr should listen on.
|
--executorPort=<port> Port that the executor should listen on.
|
||||||
--storageServicePort=<port> Port that the storage service should listen on.
|
--storageServicePort=<port> Port that the storage service should listen on.
|
||||||
--builderMgrPort=<port> Port that the buildermgr should listen on.
|
--builderMgrPort=<port> Port that the buildermgr should listen on.
|
||||||
--poolmgrUrl=<url> Poolmgr URL. Not required if --poolmgrPort is specified.
|
--executorUrl=<url> Executor URL. Not required if --executorPort is specified.
|
||||||
--routerUrl=<url> Router URL.
|
--routerUrl=<url> Router URL.
|
||||||
--etcdUrl=<etcdUrl> Etcd URL.
|
--etcdUrl=<etcdUrl> Etcd URL.
|
||||||
--storageSvcUrl=<url> StorageService URL.
|
--storageSvcUrl=<url> StorageService URL.
|
||||||
--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.
|
||||||
`
|
`
|
||||||
@@ -151,7 +144,7 @@ Options:
|
|||||||
fissionNs := getStringArgWithDefault(arguments["--fission-namespace"], "fission")
|
fissionNs := getStringArgWithDefault(arguments["--fission-namespace"], "fission")
|
||||||
envBuilderNs := getStringArgWithDefault(arguments["--envbuilder-namespace"], "fission-builder")
|
envBuilderNs := getStringArgWithDefault(arguments["--envbuilder-namespace"], "fission-builder")
|
||||||
|
|
||||||
poolmgrUrl := getStringArgWithDefault(arguments["--poolmgrUrl"], "http://poolmgr.fission")
|
executorUrl := getStringArgWithDefault(arguments["--executorUrl"], "http://executor.fission")
|
||||||
routerUrl := getStringArgWithDefault(arguments["--routerUrl"], "http://router.fission")
|
routerUrl := getStringArgWithDefault(arguments["--routerUrl"], "http://router.fission")
|
||||||
storageSvcUrl := getStringArgWithDefault(arguments["--storageSvcUrl"], "http://storagesvc.fission")
|
storageSvcUrl := getStringArgWithDefault(arguments["--storageSvcUrl"], "http://storagesvc.fission")
|
||||||
|
|
||||||
@@ -162,22 +155,18 @@ Options:
|
|||||||
|
|
||||||
if arguments["--routerPort"] != nil {
|
if arguments["--routerPort"] != nil {
|
||||||
port := getPort(arguments["--routerPort"])
|
port := getPort(arguments["--routerPort"])
|
||||||
runRouter(port, poolmgrUrl)
|
runRouter(port, executorUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
if arguments["--poolmgrPort"] != nil {
|
if arguments["--executorPort"] != nil {
|
||||||
port := getPort(arguments["--poolmgrPort"])
|
port := getPort(arguments["--executorPort"])
|
||||||
runPoolmgr(port, fissionNs, functionNs)
|
runExecutor(port, fissionNs, functionNs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if arguments["--kubewatcher"] == true {
|
if arguments["--kubewatcher"] == true {
|
||||||
runKubeWatcher(routerUrl)
|
runKubeWatcher(routerUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
if arguments["--logger"] == true {
|
|
||||||
runLogger()
|
|
||||||
}
|
|
||||||
|
|
||||||
if arguments["--timer"] == true {
|
if arguments["--timer"] == true {
|
||||||
runTimer(routerUrl)
|
runTimer(routerUrl)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,24 @@ limitations under the License.
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
uuid "github.com/satori/go.uuid"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/controller/client"
|
"github.com/fission/fission/controller/client"
|
||||||
|
"github.com/fission/fission/crd"
|
||||||
|
storageSvcClient "github.com/fission/fission/storagesvc/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func fatal(msg string) {
|
func fatal(msg string) {
|
||||||
@@ -29,6 +42,10 @@ func fatal(msg string) {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func warn(msg string) {
|
||||||
|
os.Stderr.WriteString(msg + "\n")
|
||||||
|
}
|
||||||
|
|
||||||
func getClient(serverUrl string) *client.Client {
|
func getClient(serverUrl string) *client.Client {
|
||||||
|
|
||||||
if len(serverUrl) == 0 {
|
if len(serverUrl) == 0 {
|
||||||
@@ -50,3 +67,199 @@ func checkErr(err error, msg string) {
|
|||||||
fatal(fmt.Sprintf("Failed to %v: %v", msg, err))
|
fatal(fmt.Sprintf("Failed to %v: %v", msg, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func httpRequest(method, url, body string, headers []string) *http.Response {
|
||||||
|
if method == "" {
|
||||||
|
method = "GET"
|
||||||
|
}
|
||||||
|
|
||||||
|
if method != http.MethodGet &&
|
||||||
|
method != http.MethodDelete &&
|
||||||
|
method != http.MethodPost &&
|
||||||
|
method != http.MethodPut {
|
||||||
|
fatal(fmt.Sprintf("Invalid HTTP method '%s'.", method))
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest(method, url, strings.NewReader(body))
|
||||||
|
checkErr(err, "create HTTP request")
|
||||||
|
|
||||||
|
for _, header := range headers {
|
||||||
|
headerKeyValue := strings.SplitN(header, ":", 2)
|
||||||
|
if len(headerKeyValue) != 2 {
|
||||||
|
checkErr(errors.New(""), "create request without appropriate headers")
|
||||||
|
}
|
||||||
|
req.Header.Set(headerKeyValue[0], headerKeyValue[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
checkErr(err, "execute HTTP request")
|
||||||
|
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileSize(filePath string) int64 {
|
||||||
|
info, err := os.Stat(filePath)
|
||||||
|
checkErr(err, fmt.Sprintf("stat %v", filePath))
|
||||||
|
return info.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
// upload a file and return a fission.Archive
|
||||||
|
func createArchive(client *client.Client, fileName string) *fission.Archive {
|
||||||
|
var archive fission.Archive
|
||||||
|
|
||||||
|
// fetch archive from arbitrary url if fileName is a url
|
||||||
|
if strings.HasPrefix(fileName, "http://") || strings.HasPrefix(fileName, "https://") {
|
||||||
|
fileName = downloadToTempFile(fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if fileSize(fileName) < fission.ArchiveLiteralSizeLimit {
|
||||||
|
contents := getContents(fileName)
|
||||||
|
archive.Type = fission.ArchiveTypeLiteral
|
||||||
|
archive.Literal = contents
|
||||||
|
} else {
|
||||||
|
u := strings.TrimSuffix(client.Url, "/") + "/proxy/storage"
|
||||||
|
ssClient := storageSvcClient.MakeClient(u)
|
||||||
|
|
||||||
|
// TODO add a progress bar
|
||||||
|
id, err := ssClient.Upload(fileName, nil)
|
||||||
|
checkErr(err, fmt.Sprintf("upload file %v", fileName))
|
||||||
|
|
||||||
|
archiveUrl := ssClient.GetUrl(id)
|
||||||
|
|
||||||
|
archive.Type = fission.ArchiveTypeUrl
|
||||||
|
archive.URL = archiveUrl
|
||||||
|
|
||||||
|
f, err := os.Open(fileName)
|
||||||
|
if err != nil {
|
||||||
|
checkErr(err, fmt.Sprintf("find file %v", fileName))
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
h := sha256.New()
|
||||||
|
if _, err := io.Copy(h, f); err != nil {
|
||||||
|
checkErr(err, fmt.Sprintf("calculate checksum for file %v", fileName))
|
||||||
|
}
|
||||||
|
|
||||||
|
archive.Checksum = fission.Checksum{
|
||||||
|
Type: fission.ChecksumTypeSHA256,
|
||||||
|
Sum: hex.EncodeToString(h.Sum(nil)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &archive
|
||||||
|
}
|
||||||
|
|
||||||
|
func createPackage(client *client.Client, envName, srcArchiveName, deployArchiveName, buildcmd string) *metav1.ObjectMeta {
|
||||||
|
pkgSpec := fission.PackageSpec{
|
||||||
|
Environment: fission.EnvironmentReference{
|
||||||
|
Namespace: metav1.NamespaceDefault,
|
||||||
|
Name: envName,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
var pkgStatus fission.BuildStatus = fission.BuildStatusSucceeded
|
||||||
|
|
||||||
|
if len(deployArchiveName) > 0 {
|
||||||
|
pkgSpec.Deployment = *createArchive(client, deployArchiveName)
|
||||||
|
}
|
||||||
|
if len(srcArchiveName) > 0 {
|
||||||
|
pkgSpec.Source = *createArchive(client, srcArchiveName)
|
||||||
|
// set pending status to package
|
||||||
|
pkgStatus = fission.BuildStatusPending
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(buildcmd) > 0 {
|
||||||
|
pkgSpec.BuildCommand = buildcmd
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgName := strings.ToLower(uuid.NewV4().String())
|
||||||
|
pkg := &crd.Package{
|
||||||
|
Metadata: metav1.ObjectMeta{
|
||||||
|
Name: pkgName,
|
||||||
|
Namespace: metav1.NamespaceDefault,
|
||||||
|
},
|
||||||
|
Spec: pkgSpec,
|
||||||
|
Status: fission.PackageStatus{
|
||||||
|
BuildStatus: pkgStatus,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
pkgMetadata, err := client.PackageCreate(pkg)
|
||||||
|
checkErr(err, "create package")
|
||||||
|
return pkgMetadata
|
||||||
|
}
|
||||||
|
|
||||||
|
func getContents(filePath string) []byte {
|
||||||
|
var code []byte
|
||||||
|
var err error
|
||||||
|
|
||||||
|
code, err = ioutil.ReadFile(filePath)
|
||||||
|
checkErr(err, fmt.Sprintf("read %v", filePath))
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTempDir() (string, error) {
|
||||||
|
tmpDir := uuid.NewV4().String()
|
||||||
|
tmpPath := filepath.Join(os.TempDir(), tmpDir)
|
||||||
|
err := os.Mkdir(tmpPath, 0744)
|
||||||
|
return tmpPath, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeArchiveToFile(fileName string, reader io.Reader) error {
|
||||||
|
tmpDir, err := getTempDir()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
path := filepath.Join(tmpDir, fileName+".tmp")
|
||||||
|
w, err := os.Create(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = io.Copy(w, reader)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = os.Chmod(path, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.Rename(path, fileName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// downloadToTempFile fetches archive file from arbitrary url
|
||||||
|
// and write it to temp file for further usage
|
||||||
|
func downloadToTempFile(fileUrl string) string {
|
||||||
|
reader, err := downloadURL(fileUrl)
|
||||||
|
defer reader.Close()
|
||||||
|
checkErr(err, fmt.Sprintf("download from url: %v", fileUrl))
|
||||||
|
|
||||||
|
tmpDir, err := getTempDir()
|
||||||
|
checkErr(err, "create temp directory")
|
||||||
|
|
||||||
|
tmpFilename := uuid.NewV4().String()
|
||||||
|
destination := filepath.Join(tmpDir, tmpFilename)
|
||||||
|
err = os.Mkdir(tmpDir, 0744)
|
||||||
|
checkErr(err, "create temp directory")
|
||||||
|
|
||||||
|
err = writeArchiveToFile(destination, reader)
|
||||||
|
checkErr(err, "write archive to file")
|
||||||
|
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
|
||||||
|
// downloadURL downloads file from given url
|
||||||
|
func downloadURL(fileUrl string) (io.ReadCloser, error) {
|
||||||
|
resp, err := http.Get(fileUrl)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return nil, fmt.Errorf("%v - HTTP response returned non 200 status", resp.StatusCode)
|
||||||
|
}
|
||||||
|
return resp.Body, nil
|
||||||
|
}
|
||||||
|
|||||||
+12
-13
@@ -22,10 +22,10 @@ import (
|
|||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
||||||
"github.com/fission/fission"
|
"github.com/fission/fission"
|
||||||
"github.com/fission/fission/tpr"
|
"github.com/fission/fission/crd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func envCreate(c *cli.Context) error {
|
func envCreate(c *cli.Context) error {
|
||||||
@@ -55,14 +55,13 @@ func envCreate(c *cli.Context) error {
|
|||||||
// Environment API interface version is not specified and
|
// Environment API interface version is not specified and
|
||||||
// builder image is empty, set default interface version
|
// builder image is empty, set default interface version
|
||||||
if envVersion == 0 {
|
if envVersion == 0 {
|
||||||
fmt.Println("Use default environment v1 API interface")
|
|
||||||
envVersion = 1
|
envVersion = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
env := &tpr.Environment{
|
env := &crd.Environment{
|
||||||
Metadata: api.ObjectMeta{
|
Metadata: metav1.ObjectMeta{
|
||||||
Name: envName,
|
Name: envName,
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
},
|
},
|
||||||
Spec: fission.EnvironmentSpec{
|
Spec: fission.EnvironmentSpec{
|
||||||
Version: envVersion,
|
Version: envVersion,
|
||||||
@@ -91,9 +90,9 @@ func envGet(c *cli.Context) error {
|
|||||||
fatal("Need a name, use --name.")
|
fatal("Need a name, use --name.")
|
||||||
}
|
}
|
||||||
|
|
||||||
m := &api.ObjectMeta{
|
m := &metav1.ObjectMeta{
|
||||||
Name: envName,
|
Name: envName,
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
}
|
}
|
||||||
env, err := client.EnvironmentGet(m)
|
env, err := client.EnvironmentGet(m)
|
||||||
checkErr(err, "get environment")
|
checkErr(err, "get environment")
|
||||||
@@ -121,9 +120,9 @@ func envUpdate(c *cli.Context) error {
|
|||||||
fatal("Need --image to specify env image, or use --builder to specify env builder, or use --buildcmd to specify new build command.")
|
fatal("Need --image to specify env image, or use --builder to specify env builder, or use --buildcmd to specify new build command.")
|
||||||
}
|
}
|
||||||
|
|
||||||
env, err := client.EnvironmentGet(&api.ObjectMeta{
|
env, err := client.EnvironmentGet(&metav1.ObjectMeta{
|
||||||
Name: envName,
|
Name: envName,
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
})
|
})
|
||||||
checkErr(err, "find environment")
|
checkErr(err, "find environment")
|
||||||
|
|
||||||
@@ -132,7 +131,7 @@ func envUpdate(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if env.Spec.Version == 1 && (len(envBuilderImg) > 0 || len(envBuildCmd) > 0) {
|
if env.Spec.Version == 1 && (len(envBuilderImg) > 0 || len(envBuildCmd) > 0) {
|
||||||
fatal("Environment v1 API interface doesn't supported environment builder.")
|
fatal("Version 1 Environments do not support builders. Must specify --version=2.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(envBuilderImg) > 0 {
|
if len(envBuilderImg) > 0 {
|
||||||
@@ -157,9 +156,9 @@ func envDelete(c *cli.Context) error {
|
|||||||
fatal("Need a name , use --name.")
|
fatal("Need a name , use --name.")
|
||||||
}
|
}
|
||||||
|
|
||||||
m := &api.ObjectMeta{
|
m := &metav1.ObjectMeta{
|
||||||
Name: envName,
|
Name: envName,
|
||||||
Namespace: api.NamespaceDefault,
|
Namespace: metav1.NamespaceDefault,
|
||||||
}
|
}
|
||||||
err := client.EnvironmentDelete(m)
|
err := client.EnvironmentDelete(m)
|
||||||
checkErr(err, "delete environment")
|
checkErr(err, "delete environment")
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user