You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by mr...@apache.org on 2017/05/17 17:49:33 UTC
[incubator-openwhisk-devtools] branch master updated: Able to fully
deploy OpenWhisk on Kube (#31)
This is an automated email from the ASF dual-hosted git repository.
mrutkowski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-devtools.git
The following commit(s) were added to refs/heads/master by this push:
new 3bfe674 Able to fully deploy OpenWhisk on Kube (#31)
3bfe674 is described below
commit 3bfe674a015deb658ac75c7e527a04096386c912
Author: Dan Lavine <dl...@us.ibm.com>
AuthorDate: Wed May 17 12:49:31 2017 -0500
Able to fully deploy OpenWhisk on Kube (#31)
* Deploy OpenWhisk Nginx to Kube
* Build custom nginx image that include wsk cli and blackbox
* Can only deploy with nginx certs for 'localhost'
* Able to deploy routemgmt to Kube
* Add extra configurations for zookeeper and kafka.
Able to deploy kafka properly
* Add troubleshooting section for Kafka
* Update deployment for controller to mach new master configurations
* give more time for pods to deploy
* set docker0 to promiscuous mode in travis
* Print logs for configure pod in ci when it passes or fails.
* wait until nginx is up and running
* update timeout for travis and remove extra comments
* Create secrets for kube users after deployment
* Update nginx image to have proper wsk location
* Update CI to perform wsk actions
* use sudo when setting ip link and Sleep before performing action
* Update pull policy to always pull images
* Fixup travis CI timeouts
* Update README
---
kubernetes/.travis/build.sh | 49 +++++-
kubernetes/.travis/setup.sh | 4 +-
kubernetes/Dockerfile | 7 +-
kubernetes/README.md | 181 ++++++++++++++++-----
kubernetes/ansible-kube/edge.yml | 9 +
.../environments/kube/files/controller.yml | 28 +++-
.../environments/kube/files/invoker.yml | 4 +-
.../environments/kube/files/nginx-service.yml | 22 +++
.../ansible-kube/environments/kube/files/nginx.yml | 52 ++++++
.../environments/kube/files/zookeeper-service.yml | 6 +
.../environments/kube/files/zookeeper.yml | 4 +
.../ansible-kube/environments/kube/group_vars/all | 10 +-
kubernetes/ansible-kube/openwhisk.yml | 6 +-
.../ansible-kube/roles/consul/tasks/deploy.yml | 4 +-
.../ansible-kube/roles/controller/tasks/deploy.yml | 6 +-
.../ansible-kube/roles/invoker/tasks/deploy.yml | 2 +-
.../ansible-kube/roles/kafka/tasks/deploy.yml | 2 +-
.../ansible-kube/roles/nginx/tasks/deploy.yml | 53 ++++++
.../roles/nginx/templates/nginx.conf.j2 | 68 ++++++++
.../roles/nginx/templates/secrets.conf.j2 | 8 +
.../ansible-kube/roles/routemgmt/tasks/deploy.yml | 6 +
kubernetes/ansible-kube/tasks/initdb.yml | 105 +++---------
.../ansible-kube/tasks/installOpenwhiskCatalog.yml | 34 ++++
.../ansible-kube/tasks/writeWhiskProperties.yml | 2 +-
.../ansible-kube/templates/whisk.properties.j2 | 15 +-
kubernetes/configure/cleanup.sh | 7 +
kubernetes/configure/configure.sh | 13 +-
kubernetes/docker/build.sh | 64 ++++++++
kubernetes/docker/nginx/Dockerfile | 4 +
29 files changed, 617 insertions(+), 158 deletions(-)
diff --git a/kubernetes/.travis/build.sh b/kubernetes/.travis/build.sh
index 07ab7b5..2d7af55 100755
--- a/kubernetes/.travis/build.sh
+++ b/kubernetes/.travis/build.sh
@@ -15,9 +15,13 @@ cd $ROOTDIR
kubectl apply -f configure/openwhisk_kube_namespace.yml
kubectl apply -f configure/configure_whisk.yml
+sleep 5
+
+CONFIGURE_POD=$(kubectl get pods --all-namespaces -o wide | grep configure | awk '{print $2}')
+
PASSED=false
TIMEOUT=0
-until $PASSED || [ $TIMEOUT -eq 20 ]; do
+until $PASSED || [ $TIMEOUT -eq 25 ]; do
KUBE_DEPLOY_STATUS=$(kubectl -n openwhisk get jobs | grep configure-openwhisk | awk '{print $3}')
if [ $KUBE_DEPLOY_STATUS -eq 1 ]; then
PASSED=true
@@ -30,14 +34,51 @@ until $PASSED || [ $TIMEOUT -eq 20 ]; do
sleep 30
done
-kubectl get jobs --all-namespaces -o wide --show-all
-kubectl get pods --all-namespaces -o wide --show-all
-
if [ "$PASSED" = false ]; then
+ kubectl -n openwhisk logs $CONFIGURE_POD
+ kubectl get jobs --all-namespaces -o wide --show-all
+ kubectl get pods --all-namespaces -o wide --show-all
+
echo "The job to configure OpenWhisk did not finish with an exit code of 1"
exit 1
fi
echo "The job to configure OpenWhisk finished successfully"
+# Don't try and perform wsk actions the second it finishes deploying.
+# The CI ocassionaly fails if you perform actions to quickly.
+sleep 30
+
+AUTH_SECRET=$(kubectl -n openwhisk get secret openwhisk-auth-tokens -o yaml | grep 'auth_whisk_system:' | awk '{print $2}' | base64 --decode)
+WSK_PORT=$(kubectl -n openwhisk describe service nginx | grep https-api | grep NodePort| awk '{print $3}' | cut -d'/' -f1)
+
+# download the wsk cli from nginx
+wget --no-check-certificate https://127.0.0.1:$WSK_PORT/cli/go/download/linux/amd64/wsk
+chmod +x wsk
+
+# setup the wsk cli
+./wsk property set --auth $AUTH_SECRET --apihost https://127.0.0.1:$WSK_PORT
+
+# create wsk action
+cat > hello.js << EOL
+function main() {
+ return {payload: 'Hello world'};
+}
+EOL
+
+./wsk -i action create hello hello.js
+
+
+sleep 5
+
+# run the new hello world action
+RESULT=$(./wsk -i action invoke --blocking hello | grep "\"status\": \"success\"")
+
+if [ -z "$RESULT" ]; then
+ echo "FAILED! Could not invoked custom action"
+ exit 1
+fi
+
+echo "PASSED! Deployed openwhisk and invoked custom action"
+
# push the images to an official repo
diff --git a/kubernetes/.travis/setup.sh b/kubernetes/.travis/setup.sh
index 554ea64..96d5f4d 100755
--- a/kubernetes/.travis/setup.sh
+++ b/kubernetes/.travis/setup.sh
@@ -3,6 +3,9 @@
TAG=v1.5.5
+# set docker0 to promiscuous mode
+sudo ip link set docker0 promisc on
+
# install etcd
wget https://github.com/coreos/etcd/releases/download/v3.0.14/etcd-v3.0.14-linux-amd64.tar.gz
tar xzf etcd-v3.0.14-linux-amd64.tar.gz
@@ -10,7 +13,6 @@ sudo mv etcd-v3.0.14-linux-amd64/etcd /usr/local/bin/etcd
rm etcd-v3.0.14-linux-amd64.tar.gz
rm -rf etcd-v3.0.14-linux-amd64
-
# download kubectl
wget https://storage.googleapis.com/kubernetes-release/release/$TAG/bin/linux/amd64/kubectl
chmod +x kubectl
diff --git a/kubernetes/Dockerfile b/kubernetes/Dockerfile
index 5bbbdad..e4671b8 100644
--- a/kubernetes/Dockerfile
+++ b/kubernetes/Dockerfile
@@ -9,6 +9,7 @@ RUN apt-get -y update && \
apt-get install -y \
git \
curl \
+ wget \
apt-transport-https \
ca-certificates \
python-pip \
@@ -33,14 +34,10 @@ RUN git clone https://github.com/openwhisk/openwhisk && \
# Change this to https://github.com/openwhisk/openwhisk-devtools when committing to master
COPY ansible-kube /openwhisk-devtools/kubernetes/ansible-kube
COPY configure /openwhisk-devtools/kubernetes/configure
+COPY wsk /openwhisk/bin/wsk
# install kube dependencies
# Kubernetes assumes that the version is 1.5.0+
RUN wget https://storage.googleapis.com/kubernetes-release/release/v1.5.0/bin/linux/amd64/kubectl && \
chmod +x kubectl && \
mv kubectl /usr/local/bin/kubectl
-
-# install wsk cli
-RUN wget https://openwhisk.ng.bluemix.net/cli/go/download/linux/amd64/wsk && \
- chmod +x wsk && \
- mv wsk /openwhisk/bin/wsk
diff --git a/kubernetes/README.md b/kubernetes/README.md
index 9c59105..0ce66bc 100644
--- a/kubernetes/README.md
+++ b/kubernetes/README.md
@@ -19,27 +19,51 @@ The scripts and Docker images should be able to:
1. Build the Docker image used for deploying OpenWhisk.
2. Uses a Kubernetes job to deploy OpenWhisk.
-Currently, not all of the OpenWhisk components are deployed.
-So far, it will create Kube Deployments for:
-
-* couchdb
-* consul
-* controller
-* invoker
-
-To track the process, check out this [issue](https://github.com/openwhisk/openwhisk-devtools/issues/14).
-
-## Kubernetes Requirements
-
-* Kubernetes needs to be version 1.5+
-* Kubernetes has [Kube-DNS](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/) deployed
+## Requirements and Limitations
+#### Limitations
+
+As part of the deployment process, OpenWhisk needs to generate a CA-cert
+for Nginx and currently it has a static dns entry. Because of this, you
+will need to connect to OpenWhisk using the insecure mode (e.g. `wsk -i`).
+There is future work to make this CA-cert configurable.
+
+For now, OpenWhisk relies on part of the underlying infrastructure that Kube
+is running on. When deploying the Invoker for OpenWhisk, it mounts the hosts
+Docker socket. This way OpenWhisk can quickly provision actions and does not
+have to run Docker inside of Docker.
+
+A couple of components for OpenWhisk on Kube deployment strategy requires custom
+built Docker images. One such component is Nginx and currently resides at
+[danlavine/whisk_nginx](https://hub.docker.com/r/danlavine/whisk_nginx/). There
+is currently and open [issue](https://github.com/openwhisk/openwhisk/issues/2152)
+to make a public image and once it is resolved, then we can switch to the public image.
+
+The second Docker image this deployment strategy relies on is the OpenWhisk
+configuration image. For now, it is hosted at
+[danlavine/whisk_config](https://hub.docker.com/r/danlavine/whisk_config/),
+but ideally an official images can be built an maintained at some point.
+If you would like to build your own deployment image, see
+[Manually Build Custom Docker Files](#manually-building-custom-docker-files)
+
+Lastly, since OpenWhisk is configured/deployed via a Kubernetes Pod it requires
+the correct kubectl version to be built into `danlavine/whisk_config`. For now,
+there is only a version for Kube 1.5, and one can be built for 1.6, but there
+is no CI to test it against at the moment.
+
+#### Requirements
+
+Because of the limitations mentioned above, all requirments to deploy OpenWhisk
+on Kubernetes need to be met.
+
+**Kubernetes**
+* Kube version 1.5.0-1.5.5
+* Kubernetes has [KubeDNS](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/) deployed
* (Optional) Kubernetes Pods can receive public addresses.
This will be required if you wish to reach Nginx from outside
of the Kubernetes cluster's network.
-At this time, we are not sure as to the total number of resources required
-to deploy OpenWhisk On Kubernetes. Once all of the process are running in
-Pods we will be able to list those.
+**OpenWhisk**
+* Docker version 1.12+
## Quick Start
@@ -61,44 +85,115 @@ setup the OpenWhisk environment.
kubectl apply -f configure/configure_whisk.yml
```
+To see what is happening during the deployment process,
+you should be able to see the logs from the configuration VM.
-## Manually Building Custom Docker Files
-#### Building the Docker File That Deploys OpenWhisk
+```
+kubectl -n openwhisk logs configure-openwhisk-XXXXX
+```
+
+Once the configuration job sucessfuly finishes, you should will need to
+get the auth tokens used to setup OpenWhisk. As part of the deployment
+process, we store these tokens in Kubernetes
+[secrets](https://kubernetes.io/docs/concepts/configuration/secret/).
+To get these tokens, you can run the following command:
+
+```
+kubectl -n openwhisk get secret openwhisk-auth-tokens -o yaml
+```
+
+To use the secrets you will need to base64 decode them. E.g:
+
+```
+export AUTH_SECRET=$(kubectl -n openwhisk get secret openwhisk-auth-tokens -o yaml | grep 'auth_whisk_system:' | awk '{print $2}' | base64 --decode)
+```
+
+From here, you will now need to get the publicly available address
+of Nginx.
+ 1. Obtain the IP address of the Kubernetes nodes.
+
+ ```
+ kubectl get nodes
+ ```
+
+ 2. Obtain the public port for the Kubernetes Nginx Service
+
+ ```
+ kubectl -n openwhisk describe service nginx
+ ```
-The Docker image responsible for deploying OpenWhisk can be built using following command:
+ From here you should note the port used for the api endpoint. E.g:
+
+ ```
+ export WSK_PORT=$(kubectl -n openwhisk describe service nginx | grep https-api | grep NodePort| awk '{print $3}' | cut -d'/' -f1)
+ ```
+
+Now you should be able to setup the wsk cli like normal and interact with
+Openwhisk.
```
-docker build .
+wsk property set --auth $AUTH_SECRET --apihost https://[nginx_ip]:$WSK_PORT
```
-This image must then be re-tagged and pushed to a public
-docker repo. Currently, while this project is in development,
-the docker image is built and published [here](https://hub.docker.com/r/danlavine/whisk_config/),
-until an official repo is set up. If you would like to change
-this image to one you created, then make sure to update the
-[configure_whisk.yml](./configure/configure_whisk.yml) with your image.
+## Manually Building Custom Docker Files
+
+There are two images that are required when deploying OpenWhisk on Kube,
+Nginx and the OpenWhisk configuration image.
+
+To build these images, there is a helper script to build the
+required dependencies and build the docker images itself. For example,
+the wsk cli is built locally and then coppied into these images.
-## Manually building Kube Files
-#### Deployments and Services
+The script takes in 2 arguments:
+1. (Required) The first argument is the Docker account to push the built images
+ to. For Nginx, it will tag the image as `account_name/whisk_nginx:latest`
+ and the OpenWhisk configuration image will be tagged `account_name/whisk_config:dev`.
+
+ NOTE: **log into Docker** before running the script or it will
+ fail to properly upload the docker images.
+
+2. (Optional) The second argument is the location of where the
+ [OpenWhisk](https://github.com/openwhisk/openwhisk) repo is installed
+ locally. By default it assumes that this repo exists at
+ `$HOME/workspace/openwhisk`.
+
+If you plan on building your own images and would like to change from `danlavine's`,
+then make sure to update the
+[configure_whisk.yml](configure/configure_whisk.yml) and
+[nginx](ansible-kube/environments/kube/files/nginx.yml) with your images.
+
+To run the script, use the command:
+
+```
+docker/build <username> <(optional) openwhisk dir>
+```
+
+## Editing the Openwhisk Kube Deployment
+#### Kubernetes Deployments and Services
The current Kube Deployment and Services files that define the OpenWhisk
-cluster can be found [here](ansible/environments/kube/files). Only one
+cluster can be found [here](ansible-kube/environments/kube/files). Only one
instance of each OpenWhisk process is created, but if you would like
to increase that number, then this would be the place to do it. Simply edit
-the appropriate file and rebuild the
-[Docker File That Deploys OpenWhisk](#building-the-docker-file-that-deploys-openWhisk)
+the appropriate file and
+[Manually Build Custom Docker Files](#manually-building-custom-docker-files)
## Development
#### Local Kube Development
There are a couple ways to bring up Kubernetes locally and currently we
-are using [kubeadm](https://kubernetes.io/docs/getting-started-guides/kubeadm/)
-with [Callico](https://www.projectcalico.org/) for the
+are using the common `local-up-cluster.sh` script. Take a look at what
+[travis](.travis/setup.sh) does to bring everything up with KubeDNS support.
+
+[Kubeadm](https://kubernetes.io/docs/getting-started-guides/kubeadm/)
+can be deployed with [Callico](https://www.projectcalico.org/) for the
[network](http://docs.projectcalico.org/v2.1/getting-started/kubernetes/installation/hosted/kubeadm/).
-By default kubeadm runs with Kube-DNS already enabled and the instructions
-will install a Kube version greater the v1.5. Using this deployment method
-everything is running on one host and nothing special has to be
-done for network configurations when communicating with Kube Pods.
+By default kubeadm runs with KubeDNS already enabled, but please make sure
+to install Kubeadm for Kube version 1.5.
+
+**Minikube is not supported** at this time because it uses an old version
+of docker (1.11.x). See the the [Requirements and Limitations](#requirements-and-limitations)
+section for more info.
#### Deploying OpenWhisk on Kubernetes
@@ -118,3 +213,13 @@ services and jobs. For this, you can run the following script:
```
./kube_environment/cleanup.sh
```
+## Troubleshooting
+#### Kafka
+
+When deploying Kubernetes on Ubuntu 14.04 with the `local_up_cluster.sh` scripts,
+you might need to allow kube pods to communicate with themselves over KubeDNS.
+To enable this on the Docker network, you will need to run the following command:
+
+```
+ip link set docker0 promisc on
+```
diff --git a/kubernetes/ansible-kube/edge.yml b/kubernetes/ansible-kube/edge.yml
new file mode 100644
index 0000000..5a0a387
--- /dev/null
+++ b/kubernetes/ansible-kube/edge.yml
@@ -0,0 +1,9 @@
+---
+# This playbook deploys Openwhisk Edge servers.
+# The edge is usually populated with NGINX serving as proxy.
+# The CLI also gets built and published for downloading from NGINX.
+# SDKs for blackbox and iOS get published to NGINX also.
+
+- hosts: edge
+ roles:
+ - nginx
diff --git a/kubernetes/ansible-kube/environments/kube/files/controller.yml b/kubernetes/ansible-kube/environments/kube/files/controller.yml
index d53ade6..4b27d74 100644
--- a/kubernetes/ansible-kube/environments/kube/files/controller.yml
+++ b/kubernetes/ansible-kube/environments/kube/files/controller.yml
@@ -17,8 +17,9 @@ spec:
containers:
- name: controller
- imagePullPolicy: IfNotPresent
+ imagePullPolicy: Always
image: openwhisk/controller
+ command: ["/bin/bash", "-c", "/controller/bin/controller"]
ports:
- name: controller
containerPort: 8080
@@ -39,3 +40,28 @@ spec:
value: "15s"
- name: "PORT"
value: "8080"
+ - name: "WHISK_VERSION_NAME"
+ valueFrom:
+ configMapKeyRef:
+ name: controller
+ key: whisk.version.name
+ - name: "WHISK_VERSION_DATE"
+ valueFrom:
+ configMapKeyRef:
+ name: controller
+ key: whisk.version.date
+ - name: "WHISK_VERSION_BUILDNO"
+ valueFrom:
+ configMapKeyRef:
+ name: controller
+ key: whisk.version.buildno
+ - name: "JAVA_OPTS"
+ valueFrom:
+ configMapKeyRef:
+ name: controller
+ key: java.opts
+ - name: "CONTROLLER_OPTS"
+ valueFrom:
+ configMapKeyRef:
+ name: controller
+ key: controller.opts
diff --git a/kubernetes/ansible-kube/environments/kube/files/invoker.yml b/kubernetes/ansible-kube/environments/kube/files/invoker.yml
index 201e58e..7ae579e 100644
--- a/kubernetes/ansible-kube/environments/kube/files/invoker.yml
+++ b/kubernetes/ansible-kube/environments/kube/files/invoker.yml
@@ -35,9 +35,9 @@ spec:
containers:
- name: invoker
- imagePullPolicy: IfNotPresent
+ imagePullPolicy: Always
image: openwhisk/invoker
- command: [ "/bin/bash", "-c", "/invoker/bin/invoker `hostname | cut -d'-' -f2`" ]
+ command: [ "/bin/bash", "-c", "COMPONENT_NAME=$(hostname | cut -d'-' -f2) /invoker/bin/invoker `hostname | cut -d'-' -f2`" ]
env:
- name: "CONSULSERVER_HOST"
value: "consul.openwhisk"
diff --git a/kubernetes/ansible-kube/environments/kube/files/nginx-service.yml b/kubernetes/ansible-kube/environments/kube/files/nginx-service.yml
new file mode 100644
index 0000000..c1758d3
--- /dev/null
+++ b/kubernetes/ansible-kube/environments/kube/files/nginx-service.yml
@@ -0,0 +1,22 @@
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: nginx
+ namespace: openwhisk
+ labels:
+ name: nginx
+spec:
+ type: NodePort
+ selector:
+ name: nginx
+ ports:
+ - port: 80
+ targetPort: 80
+ name: http
+ - port: 443
+ targetPort: 443
+ name: https-api
+ - port: 8443
+ targetPort: 8443
+ name: https-admin
diff --git a/kubernetes/ansible-kube/environments/kube/files/nginx.yml b/kubernetes/ansible-kube/environments/kube/files/nginx.yml
new file mode 100644
index 0000000..d9780b2
--- /dev/null
+++ b/kubernetes/ansible-kube/environments/kube/files/nginx.yml
@@ -0,0 +1,52 @@
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: nginx
+ namespace: openwhisk
+ labels:
+ name: nginx
+spec:
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ name: nginx
+ spec:
+ restartPolicy: Always
+ volumes:
+ - name: nginx-certs
+ configMap:
+ name: nginx
+ items:
+ - key: "openwhisk-cert.pem"
+ path: openwhisk-cert.pem
+ - key: "openwhisk-key.pem"
+ path: openwhisk-key.pem
+ - name: nginx-conf
+ configMap:
+ name: nginx
+ items:
+ - key: "nginx.conf"
+ path: nginx.conf
+ - name: logs
+ emptyDir: {}
+ containers:
+ - name: nginx
+ imagePullPolicy: Always
+ image: danlavine/whisk_nginx
+ ports:
+ - name: http
+ containerPort: 80
+ - name: http-api
+ containerPort: 443
+ - name: https-admin
+ containerPort: 8443
+ volumeMounts:
+ - name: nginx-conf
+ mountPath: "/etc/nginx/nginx.conf"
+ subPath: "nginx.conf"
+ - name: nginx-certs
+ mountPath: "/etc/nginx/certs"
+ - name: logs
+ mountPath: "/logs"
diff --git a/kubernetes/ansible-kube/environments/kube/files/zookeeper-service.yml b/kubernetes/ansible-kube/environments/kube/files/zookeeper-service.yml
index f2f5a6c..f48773c 100644
--- a/kubernetes/ansible-kube/environments/kube/files/zookeeper-service.yml
+++ b/kubernetes/ansible-kube/environments/kube/files/zookeeper-service.yml
@@ -13,3 +13,9 @@ spec:
- port: 2181
targetPort: 2181
name: zookeeper
+ - port: 2888
+ targetPort: 2888
+ name: server
+ - port: 3888
+ targetPort: 3888
+ name: leader-election
diff --git a/kubernetes/ansible-kube/environments/kube/files/zookeeper.yml b/kubernetes/ansible-kube/environments/kube/files/zookeeper.yml
index 219d132..cd292c5 100644
--- a/kubernetes/ansible-kube/environments/kube/files/zookeeper.yml
+++ b/kubernetes/ansible-kube/environments/kube/files/zookeeper.yml
@@ -22,3 +22,7 @@ spec:
ports:
- name: zookeeper
containerPort: 2181
+ - name: server
+ containerPort: 2888
+ - name: leader-election
+ containerPort: 3888
diff --git a/kubernetes/ansible-kube/environments/kube/group_vars/all b/kubernetes/ansible-kube/environments/kube/group_vars/all
index 9b13574..80dee7e 100644
--- a/kubernetes/ansible-kube/environments/kube/group_vars/all
+++ b/kubernetes/ansible-kube/environments/kube/group_vars/all
@@ -18,6 +18,7 @@ db_username: couch_user
db_password: couch_password
db_auth: "subjects"
db_prefix: "ubuntu_kube-1-4-1_"
+db_split_actions_and_activations: true
# apigw db credentials minimum read/write
db_apigw_username: "couch_user"
@@ -28,18 +29,19 @@ apigw_initdb: true
# API GW connection configuration
apigw_auth_user: ""
apigw_auth_pwd: ""
-apigw_host: "http://edge.openwhisk:9000/v1"
-apigw_host_v2: "http://edge.openwhisk:9000/v2"
+apigw_host: "nginx.openwhisk"
+apigw_host_v2: "nginx.openwhisk"
+whisk_api_host_name: "nginx.openwhisk"
# consul properties
consul_host: consul.openwhisk
consul_conf_dir: /tmp/consul
-# edge properties
+# nginx properties
nginx_conf_dir: /tmp/nginx
cli_nginx_dir: "/tmp/nginx/cli/go/download"
-edge_host: edge.openwhisk
+nginx_host: nginx.openwhisk
# controller properties
controller_host: controller.openwhisk
diff --git a/kubernetes/ansible-kube/openwhisk.yml b/kubernetes/ansible-kube/openwhisk.yml
index a5beaa3..94dfcfe 100644
--- a/kubernetes/ansible-kube/openwhisk.yml
+++ b/kubernetes/ansible-kube/openwhisk.yml
@@ -11,6 +11,6 @@
- include: invoker.yml
-#- include: edge.yml
-#
-#- include: routemgmt.yml
+- include: edge.yml
+
+- include: routemgmt.yml
diff --git a/kubernetes/ansible-kube/roles/consul/tasks/deploy.yml b/kubernetes/ansible-kube/roles/consul/tasks/deploy.yml
index 54c47a0..c7f61e4 100644
--- a/kubernetes/ansible-kube/roles/consul/tasks/deploy.yml
+++ b/kubernetes/ansible-kube/roles/consul/tasks/deploy.yml
@@ -30,8 +30,8 @@
body: 'true'
register: result
until: result.status == 200
- retries: 12
- delay: 5
+ retries: 20
+ delay: 10
when: "'consul_servers' in group_names"
- name: delete is alive token from Consul Server/Agent
diff --git a/kubernetes/ansible-kube/roles/controller/tasks/deploy.yml b/kubernetes/ansible-kube/roles/controller/tasks/deploy.yml
index aaba253..43c7407 100644
--- a/kubernetes/ansible-kube/roles/controller/tasks/deploy.yml
+++ b/kubernetes/ansible-kube/roles/controller/tasks/deploy.yml
@@ -1,5 +1,7 @@
---
# This role will install Controller in group 'controllers' in the environment inventory
+- name: create controller config map
+ shell: "kubectl create configmap controller --from-literal=whisk.version.name={{whisk_version_name}} --from-literal=whisk.version.date={{whisk.version.date}} --from-literal=whisk.version.buildno={{docker_image_tag}} --from-literal=java.opts=-Xmx{{controller.heap}} --from-literal=controller.opts={{controller.arguments}}"
- name: create controller deployment
shell: "kubectl apply -f {{kube_pod_dir}}/controller.yml"
@@ -19,7 +21,7 @@
shell: "kubectl -n openwhisk exec {{ item[0] }} -- bash -c 'curl -I http://0.0.0.0:8080/ping'"
register: result
until: (result.rc == 0) and (result.stdout.find("200 OK") != -1)
- retries: 12
- delay: 5
+ retries: 20
+ delay: 10
with_items:
- ["{{ controller_pods }}"]
diff --git a/kubernetes/ansible-kube/roles/invoker/tasks/deploy.yml b/kubernetes/ansible-kube/roles/invoker/tasks/deploy.yml
index f943f24..aea853b 100644
--- a/kubernetes/ansible-kube/roles/invoker/tasks/deploy.yml
+++ b/kubernetes/ansible-kube/roles/invoker/tasks/deploy.yml
@@ -10,6 +10,6 @@
url: "http://invoker-{{ item }}.invoker.openwhisk:{{ invoker_port }}/ping"
register: result
until: result.status == 200
- retries: 20
+ retries: 50
delay: 20
with_sequence: start=0 count={{ invoker_count }}
diff --git a/kubernetes/ansible-kube/roles/kafka/tasks/deploy.yml b/kubernetes/ansible-kube/roles/kafka/tasks/deploy.yml
index 1b15158..4b46c37 100644
--- a/kubernetes/ansible-kube/roles/kafka/tasks/deploy.yml
+++ b/kubernetes/ansible-kube/roles/kafka/tasks/deploy.yml
@@ -64,7 +64,7 @@
with_sequence: start=0 count={{ invoker_count }}
- name: create the invoker topics
- shell: " kubectl exec {{ item[0] }} -c kafka -- bash -c 'unset JMX_PORT; kafka-topics.sh --create --topic invoke{{ item[1] }} --replication-factor 1 --partitions 1 --zookeeper {{ zookeeper_host }}:{{ zookeeper.port }}'"
+ shell: " kubectl exec {{ item[0] }} -c kafka -- bash -c 'unset JMX_PORT; kafka-topics.sh --create --topic invoker{{ item[1] }} --replication-factor 1 --partitions 1 --zookeeper {{ zookeeper_host }}:{{ zookeeper.port }}'"
register: command_result
failed_when: "not ('Created topic' in command_result.stdout or 'already exists' in command_result.stdout)"
with_nested:
diff --git a/kubernetes/ansible-kube/roles/nginx/tasks/deploy.yml b/kubernetes/ansible-kube/roles/nginx/tasks/deploy.yml
new file mode 100644
index 0000000..f70934d
--- /dev/null
+++ b/kubernetes/ansible-kube/roles/nginx/tasks/deploy.yml
@@ -0,0 +1,53 @@
+---
+# This role starts a nginx component
+
+- name: ensure nginx config directory exists
+ file:
+ path: "{{ nginx_conf_dir }}"
+ state: directory
+
+- name: copy template from local to remote in nginx config directory
+ template:
+ src: nginx.conf.j2
+ dest: "{{ nginx_conf_dir }}/nginx.conf"
+
+- name: copy cert files from local to remote in nginx config directory
+ copy:
+ src: "files/"
+ dest: "{{ nginx_conf_dir }}"
+
+- name: create configmap
+ shell: "kubectl create configmap nginx --from-file={{ nginx_conf_dir }}/nginx.conf --from-file={{ nginx_conf_dir }}/genssl.sh --from-file={{ nginx_conf_dir }}/openwhisk-key.pem --from-file={{ nginx_conf_dir }}/openwhisk-cert.pem --from-file={{ nginx_conf_dir }}/openwhisk-request.csr"
+
+- name: create nginx pod
+ shell: "kubectl create -f {{kube_pod_dir}}/nginx.yml"
+
+# TODO Rebplace this with a proper uri request once certs have been configured correctly
+- name: wait until nginx is up and running
+ shell: "curl -k https://{{ nginx_host }}:{{ nginx.port.api }}"
+ register: result
+ until: (result.rc == 0) and (result.stdout != "")
+ retries: 20
+ delay: 10
+
+- name: get whisk system key
+ shell: "cat {{ playbook_dir }}/files/auth.whisk.system | base64 --wrap=0"
+ register: auth_whisk_system_var
+
+- name: get whisk system key
+ shell: "cat {{ playbook_dir }}/files/auth.guest | base64 --wrap=0"
+ register: auth_guest_var
+
+- name: set facts
+ set_fact:
+ auth_whisk_system: "{{ auth_whisk_system_var.stdout }}"
+ auth_guest: "{{ auth_guest_var.stdout }}"
+
+- name: fill secret template
+ template:
+ src: secrets.conf.j2
+ dest: "{{ nginx_conf_dir }}/secrets.yml"
+
+- name: create the secrets yaml
+ shell: "kubectl apply -f {{ nginx_conf_dir }}/secrets.yml"
+
diff --git a/kubernetes/ansible-kube/roles/nginx/templates/nginx.conf.j2 b/kubernetes/ansible-kube/roles/nginx/templates/nginx.conf.j2
new file mode 100644
index 0000000..ddd1fc1
--- /dev/null
+++ b/kubernetes/ansible-kube/roles/nginx/templates/nginx.conf.j2
@@ -0,0 +1,68 @@
+{# this template is used to generate a nginx.conf for booting a nginx server based on the given environment inventory #}
+
+events {
+{# default: 1024 #}
+ worker_connections 4096;
+}
+
+http {
+{# allow large uploads, need to thread proper limit into here #}
+ client_max_body_size 50M;
+
+ rewrite_log on;
+{# change log format to display the upstream information #}
+ log_format combined-upstream '$remote_addr - $remote_user [$time_local] '
+ '$request $status $body_bytes_sent '
+ '$http_referer $http_user_agent $upstream_addr';
+ access_log /logs/nginx_access.log combined-upstream;
+
+ server {
+ listen 443 default ssl;
+
+ # match namespace, note while OpenWhisk allows a richer character set for a
+ # namespace, not all those characters are permitted in the (sub)domain name;
+ # if namespace does not match, no vanity URL rewriting takes place.
+ server_name ~^(?<namespace>[0-9a-zA-Z-]+)\.{{ whisk_api_localhost_name | default(whisk_api_host_name) | default(whisk_api_localhost_name_default) }}$;
+
+ ssl_session_cache shared:SSL:1m;
+ ssl_session_timeout 10m;
+ ssl_certificate /etc/nginx/certs/openwhisk-cert.pem;
+ ssl_certificate_key /etc/nginx/certs/openwhisk-key.pem;
+ ssl_verify_client off;
+ ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
+ ssl_ciphers RC4:HIGH:!aNULL:!MD5;
+ ssl_prefer_server_ciphers on;
+ proxy_ssl_session_reuse off;
+
+ # proxy to the web action path
+ location / {
+ if ($namespace) {
+ rewrite /(.*) /api/v1/web/${namespace}/$1 break;
+ }
+ proxy_pass http://{{ controller_host }}:{{ controller.port }};
+ proxy_read_timeout 70s; # 60+10 additional seconds to allow controller to terminate request
+ }
+
+ # proxy to 'public/html' web action by convention
+ location = / {
+ if ($namespace) {
+ rewrite ^ /api/v1/web/${namespace}/public/index.html break;
+ }
+ proxy_pass http://{{ controller_host }}:{{ controller.port }};
+ proxy_read_timeout 70s; # 60+10 additional seconds to allow controller to terminate request
+ }
+
+ location /blackbox-0.1.0.tar.gz {
+ root /etc/nginx;
+ }
+
+ location /OpenWhiskIOSStarterApp.zip {
+ return 301 https://github.com/openwhisk/openwhisk-client-swift/releases/download/0.2.3/starterapp-0.2.3.zip;
+ }
+
+ location /cli/go/download {
+ autoindex on;
+ root /etc/nginx;
+ }
+ }
+}
diff --git a/kubernetes/ansible-kube/roles/nginx/templates/secrets.conf.j2 b/kubernetes/ansible-kube/roles/nginx/templates/secrets.conf.j2
new file mode 100644
index 0000000..ab252c3
--- /dev/null
+++ b/kubernetes/ansible-kube/roles/nginx/templates/secrets.conf.j2
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: openwhisk-auth-tokens
+type: Opaque
+data:
+ auth_whisk_system: {{ auth_whisk_system }}
+ auth_guest: {{ auth_guest }}
diff --git a/kubernetes/ansible-kube/roles/routemgmt/tasks/deploy.yml b/kubernetes/ansible-kube/roles/routemgmt/tasks/deploy.yml
new file mode 100644
index 0000000..a797e7b
--- /dev/null
+++ b/kubernetes/ansible-kube/roles/routemgmt/tasks/deploy.yml
@@ -0,0 +1,6 @@
+---
+# Install the API Gateway route management actions.
+- name: install route management actions
+ shell: ./installRouteMgmt.sh {{ catalog_auth_key }} {{ nginx_host }} {{ catalog_namespace }} {{ cli_path }} chdir="{{ openwhisk_home }}/ansible/roles/routemgmt/files"
+ environment:
+ OPENWHISK_HOME: "{{ openwhisk_home }}"
diff --git a/kubernetes/ansible-kube/tasks/initdb.yml b/kubernetes/ansible-kube/tasks/initdb.yml
index 20151fa..f20356d 100644
--- a/kubernetes/ansible-kube/tasks/initdb.yml
+++ b/kubernetes/ansible-kube/tasks/initdb.yml
@@ -1,94 +1,31 @@
---
# This task will initialize the immortal DBs in the database account.
-# This step is usually done only once per account.
+# This step is usually done only once per deployment.
-- name: check if the immortal {{ db.whisk.auth }} db with {{ db_provider }} exists?
- uri:
- url: "{{ db_protocol }}://{{ db_host }}:{{ db_port }}/{{ db.whisk.auth }}"
- method: GET
- status_code: 200,404
- user: "{{ db_username }}"
- password: "{{ db_password }}"
- force_basic_auth: yes
- register: dbexists
-
-# create only the missing db.whisk.auth
-- name: create immortal {{ db.whisk.auth }} db with {{ db_provider }}
- uri:
- url: "{{ db_protocol }}://{{ db_host }}:{{ db_port }}/{{ db.whisk.auth }}"
- method: PUT
- status_code: 200,201,202
- user: "{{ db_username }}"
- password: "{{ db_password }}"
- force_basic_auth: yes
- when: dbexists is defined and dbexists.status == 404
-
-# fetches the revision of previous view (to update it) if it exists
-- name: check for previous view in "auth" database
+- include: db/recreateDb.yml
vars:
- auth_index: "{{ lookup('file', '{{ openwhisk_home }}/ansible/files/auth_index.json') }}"
- uri:
- url: "{{ db_protocol }}://{{ db_host }}:{{ db_port }}/{{ db.whisk.auth }}/{{ auth_index['_id'] }}"
- return_content: yes
- method: GET
- status_code: 200, 404
- user: "{{ db_username }}"
- password: "{{ db_password }}"
- force_basic_auth: yes
- register: previousView
- when: dbexists is defined and dbexists.status != 404 #and mode=="updateview"
-
-- name: extract revision from previous view
- vars:
- previousContent: "{{ previousView['content']|from_json }}"
- revision: "{{ previousContent['_rev'] }}"
- auth_index: "{{ lookup('file', '{{ openwhisk_home }}/ansible/files/auth_index.json') }}"
- set_fact:
- previousContent: "{{ previousContent }}"
- updateWithRevision: "{{ auth_index | combine({'_rev': revision}) }}"
- when: previousView is defined and previousView.status != 404
-
-- name: check if a view update is required
- set_fact:
- updateView: "{{ updateWithRevision }}"
- when: previousContent is defined and previousContent != updateWithRevision
+ dbName: "{{ db.whisk.auth }}"
+ forceRecreation: False
-- name: recreate or update the index on the "auth" database
+- include: db/recreateDoc.yml
vars:
- auth_index: "{{ lookup('file', '{{ openwhisk_home }}/ansible/files/auth_index.json') }}"
- uri:
- url: "{{ db_protocol }}://{{ db_host }}:{{ db_port }}/{{ db.whisk.auth }}"
- method: POST
- status_code: 200, 201
- body_format: json
- body: "{{ updateView | default(auth_index) }}"
- user: "{{ db_username }}"
- password: "{{ db_password }}"
- force_basic_auth: yes
- when: (dbexists is defined and dbexists.status == 404) or (updateView is defined)
+ dbName: "{{ db.whisk.auth }}"
+ doc: "{{ lookup('file', '{{ item }}') }}"
+ with_items:
+ - "{{ openwhisk_home }}/ansible/files/auth_index.json"
+ - "{{ openwhisk_home }}/ansible/files/filter_design_document.json"
-- name: recreate necessary "auth" keys
+- name: create necessary "auth" keys
+ include: db/recreateDoc.yml
vars:
key: "{{ lookup('file', 'files/auth.{{ item }}') }}"
- uri:
- url: "{{ db_protocol }}://{{ db_host }}:{{ db_port }}/{{ db.whisk.auth }}"
- method: POST
- status_code: 200,201
- body_format: json
- body: >
- {
- "_id": "{{ item }}",
- "subject": "{{ item }}",
- "namespaces": [
- {
- "name": "{{ item }}",
- "uuid": "{{ key.split(":")[0] }}",
- "key": "{{ key.split(":")[1] }}"
- }
- ]
- }
- user: "{{ db_username }}"
- password: "{{ db_password }}"
- force_basic_auth: yes
+ dbName: "{{ db.whisk.auth }}"
+ doc: >
+ {
+ "_id": "{{ item }}",
+ "subject": "{{ item }}",
+ "uuid": "{{ key.split(":")[0] }}",
+ "key": "{{ key.split(":")[1] }}",
+ "namespaces": []
+ }
with_items: "{{ db.authkeys }}"
- when: dbexists is defined and dbexists.status == 404
diff --git a/kubernetes/ansible-kube/tasks/installOpenwhiskCatalog.yml b/kubernetes/ansible-kube/tasks/installOpenwhiskCatalog.yml
new file mode 100644
index 0000000..7064e27
--- /dev/null
+++ b/kubernetes/ansible-kube/tasks/installOpenwhiskCatalog.yml
@@ -0,0 +1,34 @@
+---
+# This task will install the standard actions and packages available in openwhisk-catalog repos.
+
+- set_fact:
+ catalog_location={{ item.value.location }}
+ catalog_repo_url={{ item.value.url }}
+ api_host={{ nginx_host }}
+ version="HEAD"
+ repo_update="yes"
+
+- set_fact:
+ version={{ item.value.version }}
+ when: item.value.version is defined
+
+- set_fact:
+ repo_update={{ item.value.repo_update }}
+ when: item.value.repo_update is defined
+
+- name: "ensure catalog_location directory exists"
+ file:
+ path: "{{ catalog_location }}"
+ state: directory
+
+- name: download the catalog repository to the catalog location if necessary
+ git:
+ repo: "{{ catalog_repo_url }}"
+ dest: "{{ catalog_location }}"
+ update: "{{ repo_update }}"
+ version: "{{ version }}"
+
+- name: install the catalog from the catalog location
+ shell: ./installCatalog.sh {{ catalog_auth_key }} {{ api_host }} {{ catalog_namespace }} {{ cli_path }} chdir="{{ catalog_location }}/packages"
+ environment:
+ OPENWHISK_HOME: "{{ openwhisk_home }}"
diff --git a/kubernetes/ansible-kube/tasks/writeWhiskProperties.yml b/kubernetes/ansible-kube/tasks/writeWhiskProperties.yml
index 97ec01f..d066c86 100644
--- a/kubernetes/ansible-kube/tasks/writeWhiskProperties.yml
+++ b/kubernetes/ansible-kube/tasks/writeWhiskProperties.yml
@@ -8,7 +8,7 @@
- name: update the invoker domains
set_fact:
- invoker_hosts: "{{invoker_hosts}} + ['invoker-{{item}}.invoker.openwhisk]"
+ invoker_hosts: "{{ invoker_hosts }} + [ 'invoker-{{item}}.invoker.openwhisk' ]"
with_sequence: start=0 count={{ invoker_count }}
- name: write whisk.properties template to openwhisk_home
diff --git a/kubernetes/ansible-kube/templates/whisk.properties.j2 b/kubernetes/ansible-kube/templates/whisk.properties.j2
index c983fd7..1ab149d 100644
--- a/kubernetes/ansible-kube/templates/whisk.properties.j2
+++ b/kubernetes/ansible-kube/templates/whisk.properties.j2
@@ -52,10 +52,9 @@ invoker.hosts={{ invoker_hosts | join(",") }}
controller.host={{ controller_host }}
kafka.host={{ kafka_host }}
zookeeper.host={{ zookeeper_host }}
-
-edge.host={{ groups["edge"]|first }}
-loadbalancer.host={{ groups["controllers"]|first }}
-router.host={{ groups["edge"]|first }}
+edge.host={{ nginx_host }}
+loadbalancer.host={{ controller_host }}
+router.host={{ nginx_host }}
{#
# replaced host entries
@@ -65,6 +64,9 @@ router.host={{ groups["edge"]|first }}
# controller.host={{ groups["controllers"]|first }}
# kafka.host={{ groups["kafka"]|first }}
# zookeeper.host={{ groups["kafka"]|first }}
+ # edge.host={{ groups["edge"]|first }}
+ # loadbalancer.host={{ groups["controllers"]|first }}
+ # router.host={{ groups["edge"]|first }}
#}
edge.host.apiport=443
@@ -100,12 +102,11 @@ edge.docker.endpoint={{ groups["edge"]|first }}:{{ docker.port }}
kafka.docker.endpoint={{ groups["kafka"]|first }}:{{ docker.port }}
main.docker.endpoint={{ groups["controllers"]|first }}:{{ docker.port }}
-docker.registry={{ docker_registry }}
-
# configure to use the public docker images
docker.image.prefix=openwhisk
-#docker.image.prefix={{ docker_image_prefix }}
+docker.registry={{ docker_registry }}
+#docker.image.prefix={{ docker_image_prefix }}
#use.docker.registry=false
docker.port={{ docker.port }}
docker.timezone.mount=
diff --git a/kubernetes/configure/cleanup.sh b/kubernetes/configure/cleanup.sh
index 84728f2..581d859 100755
--- a/kubernetes/configure/cleanup.sh
+++ b/kubernetes/configure/cleanup.sh
@@ -14,9 +14,12 @@ kubectl -n openwhisk delete deployment zookeeper
kubectl -n openwhisk delete deployment kafka
kubectl -n openwhisk delete deployment controller
kubectl -n openwhisk delete statefulsets invoker
+kubectl -n openwhisk delete deployment nginx
# delete configmaps
kubectl -n openwhisk delete cm consul
+kubectl -n openwhisk delete cm controller
+kubectl -n openwhisk delete cm nginx
# delete services
kubectl -n openwhisk delete service couchdb
@@ -25,3 +28,7 @@ kubectl -n openwhisk delete service zookeeper
kubectl -n openwhisk delete service kafka
kubectl -n openwhisk delete service controller
kubectl -n openwhisk delete service invoker
+kubectl -n openwhisk delete service nginx
+
+# delete secrets
+kubectl -n openwhisk delete secret openwhisk-auth-tokens
diff --git a/kubernetes/configure/configure.sh b/kubernetes/configure/configure.sh
index 89dfa94..a1e72bf 100755
--- a/kubernetes/configure/configure.sh
+++ b/kubernetes/configure/configure.sh
@@ -30,6 +30,10 @@ sed -ie "s/REPLACE_INVOKER_COUNT/$INVOKER_COUNT/g" /openwhisk-devtools/kubernete
# copy the ansible playbooks and tools to this repo
cp -R /openwhisk/ansible/ /openwhisk-devtools/kubernetes/ansible
cp -R /openwhisk/tools/ /openwhisk-devtools/kubernetes/tools
+cp -R /openwhisk/bin/ /openwhisk-devtools/kubernetes/bin
+
+mkdir -p /openwhisk-devtools/kubernetes/core
+cp -R /openwhisk/core/routemgmt /openwhisk-devtools/kubernetes/core/routemgmt
# overwrite the default openwhisk ansible with the kube ones.
cp -R /openwhisk-devtools/kubernetes/ansible-kube/. /openwhisk-devtools/kubernetes/ansible/
@@ -38,6 +42,8 @@ cp -R /openwhisk-devtools/kubernetes/ansible-kube/. /openwhisk-devtools/kubernet
kubectl proxy -p 8001 &
pushd /openwhisk-devtools/kubernetes/ansible
+ ansible-playbook -i environments/kube setup.yml
+
# Create all of the necessary services
kubectl apply -f environments/kube/files/db-service.yml
kubectl apply -f environments/kube/files/consul-service.yml
@@ -45,15 +51,18 @@ pushd /openwhisk-devtools/kubernetes/ansible
kubectl apply -f environments/kube/files/kafka-service.yml
kubectl apply -f environments/kube/files/controller-service.yml
kubectl apply -f environments/kube/files/invoker-service.yml
+ kubectl apply -f environments/kube/files/nginx-service.yml
if deployCouchDB; then
- # Create the CouchDB deployment
+ # Create and configure the CouchDB deployment
ansible-playbook -i environments/kube couchdb.yml
- # configure couch db
ansible-playbook -i environments/kube initdb.yml
ansible-playbook -i environments/kube wipe.yml
fi
# Run through the openwhisk deployment
ansible-playbook -i environments/kube openwhisk.yml
+
+ # Post deploy step
+ ansible-playbook -i environments/kube postdeploy.yml
popd
diff --git a/kubernetes/docker/build.sh b/kubernetes/docker/build.sh
index 0c1340d..f1dc30e 100755
--- a/kubernetes/docker/build.sh
+++ b/kubernetes/docker/build.sh
@@ -15,5 +15,69 @@ EndOfMessage
exit 1
fi
+
+OPENWHISK_DIR=""
+if [ -z "$2" ]; then
+cat <<- EndOfMessage
+ Second argument should be location of the OpenWhisk repo on the local
+ file system. By default, it is assumed to be at $HOME/workspace/openwhisk.
+EndOfMessage
+ OPENWHISK_DIR=$HOME/workspace/openwhisk
+else
+ OPENWHISK_DIR="$2"
+exit 1
+fi
+
+
SOURCE="${BASH_SOURCE[0]}"
SCRIPTDIR="$( dirname "$SOURCE" )"
+
+# build nginx
+pushd $SCRIPTDIR/nginx
+ pushd $OPENWHISK_DIR
+ ./gradlew tools:cli:distDocker
+ popd
+
+ # copy whisk cli to nginx directory
+ cp $OPENWHISK_DIR/bin/wsk .
+
+ mkdir -p blackbox
+ pushd blackbox
+ # copy docker sdk to dockerSkeleton in scratch space
+ cp $OPENWHISK_DIR/sdk/docker/buildAndPush.sh .
+ cp $OPENWHISK_DIR/sdk/docker/Dockerfile .
+ cp $OPENWHISK_DIR/sdk/docker/example.c .
+ cp $OPENWHISK_DIR/sdk/docker/README.md .
+
+ # rename base image in Dockerfile
+ sed -i "s|FROM dockerskeleton|FROM openwhisk/dockerskeleton|g" Dockerfile
+
+ # fix file permissions
+ chmod 0755 buildAndPush.sh
+
+ # build blackbox container artifact
+ tar -czf ../blackbox-0.1.0.tar.gz .
+ popd
+
+ NGINX_IMAGE=$(docker build . | grep "Successfully built" | awk '{print $3}')
+ docker tag $NGINX_IMAGE "$1"/whisk_nginx
+ docker push "$1"/whisk_nginx
+
+ # cleanup
+ rm wsk
+ rm blackbox-0.1.0.tar.gz
+ rm -rf blackbox
+popd
+
+# build the OpenWhisk deploy image
+pushd $SCRIPTDIR/..
+ # copy whisk cli
+ cp $OPENWHISK_DIR/bin/wsk .
+
+ WHISK_DEPLOY_IMAGE=$(docker build . | grep "Successfully built" | awk '{print $3}')
+ docker tag $WHISK_DEPLOY_IMAGE "$1"/whisk_config:dev
+ docker push "$1"/whisk_config:dev
+
+ # rm the whisk cli to keep things clean
+ rm wsk
+popd
diff --git a/kubernetes/docker/nginx/Dockerfile b/kubernetes/docker/nginx/Dockerfile
new file mode 100644
index 0000000..3a4e47b
--- /dev/null
+++ b/kubernetes/docker/nginx/Dockerfile
@@ -0,0 +1,4 @@
+FROM nginx:1.11
+
+COPY wsk /etc/nginx/cli/go/download/linux/amd64/wsk
+COPY blackbox-0.1.0.tar.gz /etc/nginx/blackbox-0.1.0.tar.gz
--
To stop receiving notification emails like this one, please contact
['"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>'].