Skip to content

Instantly share code, notes, and snippets.

@kars7e
Last active February 7, 2018 04:17
Show Gist options
  • Save kars7e/8b2289ff0faabb866a20c421436924e1 to your computer and use it in GitHub Desktop.
Save kars7e/8b2289ff0faabb866a20c421436924e1 to your computer and use it in GitHub Desktop.
Dispatch Blog Example using GKE

Prerequisite

Dispatch

If you arrived here, you should already have GKE environment ready, and Dispatch deployed. We will now deploy dependencies, and install our blog application.

Minio

Minio is a S3 compatible object store, we use it to store blog posts. You can deploy a minio server locally or use S3 instead.

Here we briefly provide a simple way to deploy minio in a kubernetes cluster with helm, if you have deployed dispatch, you should already have a kubernetes cluter and helm ready.

$ export MINIO_ACCESS_KEY=blogaccess
$ export MINIO_SECRET_KEY=blogsecret

$ helm install --name minio --namespace minio --set serviceType=LoadBalancer,accessKey=$MINIO_ACCESS_KEY,secretKey=$MINIO_SECRET_KEY stable/minio

You need to keep a note of minio credentials, including hostname, port, accessKey, secretKey.

You can retrieve the minio IP (Minio Host in our example) by running:

$ export MINIO_HOST=$(kubectl get svc -n minio -o json | jq  -r '.items[0].status.loadBalancer.ingress[0].ip')

Because we are using GKE with Load Balancer, we can use Minio predefined port 9000:

$ export MINIO_PORT=9000

The accessKey and secretKey are stored in kubernetes secrets:

$ echo $(kubectl get secret minio-minio-user -n minio -o json | jq -r .data.accesskey | base64 -D)
blogaccess

Build the image

This step is optional. You can just run following command to use a pre-built image:

$ export BASE_IMAGE=berndtj/dispatch-nodejs6-blog-webapp:0.0.1-dev1

And go to "Register the image with Dispatch" step.

To build the image yourself, use a hosted docker registry (docker hub):

  1. Login to docker hub (account required):
    $ docker login
    Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
    Username (berndtj):
    Password:
    Login Succeeded
    
  2. Build the image:
    $ export BASE_IMAGE=<docker username>/dispatch-nodejs6-blog-webapp:0.0.1-dev1
    $ docker build -t $BASE_IMAGE ./examples/blog/base-image
    $ docker push $BASE_IMAGE
    

Register the image with Dispatch

$ dispatch create base-image blog-webapp-base-image $BASE_IMAGE --language=nodejs6
$ dispatch create image blog-webapp-image blog-webapp-base-image

Wait for both the base-image and image to be in the READY state:

$ dispatch get base-image
           NAME          |                            URL                             | STATUS |         CREATED DATE
--------------------------------------------------------------------------------------------------------------------------
  blog-webapp-base-image | 10.97.167.150:5000/dispatch-nodejs6-blog-webapp:0.0.1-dev1 | READY  | Sat Jan  1 13:06:40 PST 0000
$ dispatch get images
        NAME        |                  URL                   |       BASEIMAGE        | STATUS |         CREATED DATE
--------------------------------------------------------------------------------------------------------------------------
  blog-webapp-image | 10.97.167.150:5000/d5590f2e9cd3:latest | blog-webapp-base-image | READY  | Sat Jan  1 13:39:12 PST 0000

Secret

Create a secret.json file to store the minio credientials:

$ cat << EOF > secret.json
{
    "endPoint": "$MINIO_HOST",
    "port": "$MINIO_PORT",
    "accessKey": "$MINIO_ACCESS_KEY",
    "secretKey": "$MINIO_SECRET_KEY",
    "bucket": "blog"
}
EOF
$ cat secret.json
{
    "endPoint": "192.168.64.24",
    "port": "31390",
    "accessKey": "*****",
    "secretKey": "*****",
    "bucket": "blog"
}

Create dispatch secret with your just created secret.json

$ dispatch create secret blog-webapp-secret secret.json
$ dispatch get secret blog-webapp-secret
Note: secret values are hidden, please use --all flag to get them

                   ID                  |        NAME        | CONTENT
--------------------------------------------------------------------
  dc899a09-0abc-11e8-976a-922ad6cb76e3 | blog-webapp-secret | <hidden>

Upload the post.js as a Dispatch function

If you haven't cloned the dispatch repository, now is the time:

$ git clone https://github.com/vmware/dispatch.git && cd dispatch

Create a dispatch function and associate it with your just created dispatch secret.

$ dispatch create function blog-webapp-image post examples/blog/post.js --secret blog-webapp-secret

Wait for the function to be in the READY state:

$ dispatch get function post
  NAME |       IMAGE       | STATUS |         CREATED DATE
---------------------------------------------------------------
  post | blog-webapp-image | READY  | Sat Jan  1 13:43:57 PST 0000

Milestone I: Execute the uploaded function with dispatch cli

Use dispatch cli to test if your images, secrets and functions are deployed correctly and ready to be used.

$ dispatch exec post --input '{"op":"add", "post":{"id":"126", "title":"helloworld", "content":"this is a content"}}' --wait
{
    ...
    "output": {
        "post": {
            "content": "this is a content",
            "id": "126",
            "title": "helloworld"
        }
    },
    ...
    "status": "READY"
}

Try these for yourself and see what they do.

$ dispatch exec post --input '{"op":"get", "post":"126"}' --wait
$ dispatch exec post --input '{"op":"update", "post":{"id":"126", "title":"nihao", "content":"nihao"}}' --wait
$ dispatch exec post --input '{"op":"list"}' --wait
$ dispatch exec post --input '{"op":"delete", "post":{"id":"126"}}' --wait

Create APIs

APIs are used by the blog webapp client (an angular2.0 project)

Create an unauthenticated GET endpoint with path /post/list that executes the post function

$ dispatch create api list-post-api post --auth public -m GET --path /post/list --cors

Create an unauthenticated GET endpoint with path /post/get that executes the post function

$ dispatch create api get-post-api post --auth public -m GET  --path /post/get --cors

Create an unauthenticated POST endpoint with the path /post/add that executes the post function

$ dispatch create api add-post-api post --auth public -m POST  --path /post/add --cors

Create an unauthenticated PATCH endpoint with the path /post/update that executes the post function

$ dispatch create api update-post-api post --auth public -m PATCH --path /post/update --cors

Create an unauthenticated DELETE endpoint with the path /post/delete that executes the post function

$ dispatch create api delete-post-api post --auth public -m DELETE --path /post/delete --cors

The post function is responsible for determining the operation, parsing url parameters, and performing the correct operation.

Check the status of the APIs:

$ dispatch get api
       NAME       | FUNCTION | PROTOCOL  | METHOD | DOMAIN |     PATH     |  AUTH  | STATUS | ENABLED
-------------------------------------------------------------------------------------------------------
  update-post-api | post     | http      | PATCH  |        | /post/update | public | READY  | true
                  |          | https     |        |        |              |        |        |
-------------------------------------------------------------------------------------------------------
  delete-post-api | post     | http      | DELETE |        | /post/delete | public | READY  | true
                  |          | https     |        |        |              |        |        |
-------------------------------------------------------------------------------------------------------
  list-post-api   | post     | http      | GET    |        | /post/list   | public | READY  | true
                  |          | https     |        |        |              |        |        |
-------------------------------------------------------------------------------------------------------
  get-post-api    | post     | http      | GET    |        | /post/get    | public | READY  | true
                  |          | https     |        |        |              |        |        |
-------------------------------------------------------------------------------------------------------
  add-post-api    | post     | http      | POST   |        | /post/add    | public | READY  | true
                  |          | https     |        |        |              |        |        |
-------------------------------------------------------------------------------------------------------

Milestone II: Execute the function via API Gateway

In this milestone, you want to test if your function works well via dispatch api-gateway.

Look into the spreadsheet with GKE env info. Copy the value from "API Gateway IP" column for your environment. Run following command (replace COPIED_IP with the IP from the spreadsheet):

$ export DISPATCH_API_URL=https://COPIED_IP:443

Add a new blog post

$ curl -s -k -X POST ${DISPATCH_API_URL}/post/add -d '{
    "op": "add",
    "post":{
        "id": "1234",
        "title": "foo",
        "content":"bar bar bar"
    }
}' | jq
{
  "post": {
    "content": "bar bar bar",
    "title": "foo",
    "id": "1234"
  }
}

Get the newly created blog post

$ curl -s -k -X GET ${DISPATCH_API_URL}/post/get?op=get\&post=1234 | jq
{
  "post": {
    "content": "bar bar bar",
    "title": "foo",
    "id": "1234"
  }
}

Get a list of blog posts

$ curl -s -k -X GET ${DISPATCH_API_URL}/post/list?op=list | jq
{
  "post": [
    {
      "content": "bar bar bar",
      "title": "foo",
      "id": "1234"
    },
    {
      "content": "this is a content",
      "title": "helloworld",
      "id": "126"
    }
  ]
}

Update a blog post

$ curl -s -k -X PATCH ${DISPATCH_API_URL}/post/update -d '{
    "op": "update",
    "post":{
        "id": "1234",
        "title": "foo",
        "content":"foo foo foo"
    }
}' | jq
{
  "post": {
    "content": "foo foo foo",
    "title": "foo",
    "id": "1234"
  }
}

Delete a blog post

$ curl -s -k -X DELETE ${DISPATCH_API_URL}/post/delete -d '{
    "op": "delete",
    "post": { "id": "1234"}
}' | jq
{
  "post": {
    "id": "1234"
  }
}

After completing this milestone, it is a good time to deploy a front-end web-app(UI), which provides a friendly user interface for your blog.

Please go ahead and check dispatch-example-blog-web-client

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment