# 🇬🇧 OpenFaas is also a PaaS - Part 2: Vert-x and GitLab

Yesterday, I explained how to use OpenFaaS as a PaaS to deploy an ExpressJS web application or micro-services, and it's here: OpenFaas is also a PaaS - Part 1.

Today, I want to do the same thing, but with a Kotlin Vert-x application, and I will manage the build and the deployment with GitLab. I use my own GitLab instance, my own runner and my own (unsecure) Docker registry, but it's easy to reproduce in your own environment (Last, year I wrot a blog post to explain the setup of OpenFaas and a Docker registry: First contact with OpenFaaS).

👋 Remarks:

  • if you need help on the GitLab part, ping me
  • your GitLab runner should embed Java JDK, OpenFaaS CLI and Docker client
  • even if you don't use GitLab, you can use the first part of this blog post

# Create the Vert-x web application

  • I will use Kotlin

# Generate the Vert-x project

Vert-x website provides nice starter kits, so somewhere on your laptop, type these commands

curl -G https://start.vertx.io/starter.zip \
  -d "groupId=garden.bots" \
  -d "artifactId=hey-people" \
  -d "vertxVersion=4.0.0-milestone3" \
  -d "vertxDependencies=vertx-web" \
  -d "language=kotlin" \
  -d "jdkVersion=1.8" \
  -d "buildTool=maven" \
  --output hey-people.zip

unzip hey-people.zip -d hey-people

# Add the OpenFaas part

I plan to use GitLab CI to build and deploy my web application. I will deploy it to OpenFaaS in a PaaS way, so I only need (in my case) the dockerfile template from the OpenFaaS templates store:

# Dockerfile template

this command will only download the dockerfile template of OpenFaas

cd hey-people
mkdir template
curl https://codeload.github.com/openfaas/templates/tar.gz/master \
  | tar -C template -xz --strip=2 templates-master/template/dockerfile

# Dockerfile

Then, next we need a Dockerfile to dockerize our Vert-x application:

cat > Dockerfile <<EOF
FROM azul/zulu-openjdk-alpine:latest
ENV WEB_APP_JAR="hey-people-1.0.0-SNAPSHOT-fat.jar"
COPY target/\${WEB_APP_JAR} .
RUN touch /tmp/.lock
# --- run the application
CMD java -jar \$WEB_APP_JAR
EOF

Remark: as I use cat to generate my files, don't forget to escape $ like that \$

# Deployment file description

The OpenFaaS CLI need a description file with the needed information about how and where to deploy:

cat > config.deploy.yml <<EOF
version: 1.0
provider:
  name: openfaas
  gateway: ${OPENFAAS_URL}
functions:
  \${PROJECT_NAME}:
    lang: dockerfile
    handler: ./
    image: \${DOCKER_REGISTRY}/\${PROJECT_NAME}:latest
EOF

# Some changes in the source code

We are going to change the source code of the main verticle: src/main/kotlin/garden/bots/hey_people/MainVerticle.kt (it's not mandatory, but I wanted to show how to use the Vert-x router)

cd hey-people # if you are not in the project directory

cat >  src/main/kotlin/garden/bots/hey_people/MainVerticle.kt <<EOF
package garden.bots.hey_people

import io.vertx.core.AbstractVerticle
import io.vertx.core.Promise
import io.vertx.core.json.JsonObject
import io.vertx.ext.web.Router
import io.vertx.ext.web.handler.BodyHandler

class MainVerticle : AbstractVerticle() {

  override fun start(startPromise: Promise<Void>) {

    val router = Router.router(vertx)
    router.route().handler(BodyHandler.create())
    
    router.get("/hello").handler { context ->
      context.response().putHeader("content-type", "application/json;charset=UTF-8")
        .end(
          JsonObject().put("message", "👋 Hello World 🌍").encodePrettily()
        )
    }

    router.get("/").handler { context ->
      context.response().putHeader("content-type", "text/html;charset=UTF-8")
        .end("<h1>👋 Hello World 🌍</h1>")
    }

    // Don't forget: an OpenFaaS service is always listening on 8080
    val httpPort = System.getenv("PORT")?.toInt() ?: 8080

    vertx
      .createHttpServer()
      .requestHandler(router)
      .listen(httpPort) { http ->
        if (http.succeeded()) {
          startPromise.complete()
          println("HTTP server started on port 8080")
        } else {
          startPromise.fail(http.cause())
        }
      }
  }
}
EOF

Now, we are ready to test a first deployment

# First deployment (without GitLab)

We are not going to use GitLab for the first deployment. We are just going to that "by hands":

# Build the jar file

cd hey-people # if you are not in the project directory

# build the jar file
chmod +x mvnw
./mvnw clean package

# Build the web application image, push it and deploy it

we export these variables to be used by the OpenFaaS CLI

export OPENFAAS_URL=http://openfaas.test:8080
export OPENFASS_TOKEN=e073022e120dd3c3f72baaa5a0728fcc27d392ff6b68d6099f6dc2ea05b0a0ba
export PROJECT_NAME="hey-people"
export DOCKER_REGISTRY="registry.test:5000"

echo -n ${OPENFASS_TOKEN} |faas-cli login --username=admin --password-stdin

faas-cli build -f config.deploy.yml
faas-cli push -f config.deploy.yml 
faas-cli deploy -f config.deploy.yml 

# you can check
faas-cli logs hey-people

Now, you can reach:

So, if you want to develop micro-services with Vert-x (and I think it's the best Java library to do that - but it's another topic), you can see that's easy, and OpenFaaS is the perfect PaaS to host them.

Now, it's time to put our project on GitLab and manage deploymenst with GitLab CI/CD.

# GitLab part

First we will update the config.deploy.yml file like this:

cat > config.deploy.yml <<EOF
version: 1.0
provider:
  name: openfaas
  gateway: ${OPENFAAS_URL}
functions:
  \${CI_PROJECT_NAME}-\${CI_COMMIT_REF_SLUG}:
    lang: dockerfile
    handler: ./
    image: \${DOCKER_REGISTRY}/\${CI_PROJECT_NAME}-\${CI_COMMIT_REF_SLUG}:latest
EOF

Then, we need to add a .gitlab-ci.yml file to our project to describe the deployment stages and jobs:

we just reproduce the command of the previous part. But with this .gitlab-ci.yml, you will be able to deploy even the review/preview version of your web application from a feature branch (https://docs.gitlab.com/ee/ci/review_apps/ (opens new window)).

stages:
  - 📦build
  - 🐳package
  - 🚀deploy
  - 🦄deploy

🌍service_build:
  stage: 📦build
  only:
    - master
    - merge_requests
  script: |
    chmod +x mvnw
    ./mvnw clean package
    faas-cli build -f config.deploy.yml

🌏service_push:
  stage: 🐳package
  only:
    - master
    - merge_requests
  script: |
    faas-cli push -f config.deploy.yml 

🌎service_deploy:
  stage: 🚀deploy
  environment:
    name: production/${CI_PROJECT_NAME}-${CI_COMMIT_REF_SLUG}
    url:  ${OPENFAAS_URL}/function/${CI_PROJECT_NAME}-${CI_COMMIT_REF_SLUG}/
  only:
    - master
  script: |
    export OPENFAAS_URL=${OPENFAAS_URL}
    echo -n ${OPENFASS_TOKEN} | \
    faas-cli login --username=admin --password-stdin
    faas-cli deploy -f config.deploy.yml

🚧preview_service_deploy:
  stage: 🦄deploy
  environment:
    name: preview/${CI_PROJECT_NAME}-${CI_COMMIT_REF_SLUG}
    url:  ${OPENFAAS_URL}/function/${CI_PROJECT_NAME}-${CI_COMMIT_REF_SLUG}/
    on_stop: 🗑stop_preview_service
  only:
    - merge_requests
  script: |
    export OPENFAAS_URL=${OPENFAAS_URL}
    echo -n ${OPENFASS_TOKEN} | \
    faas-cli login --username=admin --password-stdin
    faas-cli deploy -f config.deploy.yml

🗑stop_preview_service:
  stage: 🦄deploy
  only:
    - merge_requests
  when: manual
  environment:
    name: preview/${CI_PROJECT_NAME}-${CI_COMMIT_REF_SLUG}
    action: stop
  script: |
    faas-cli remove -f config.deploy.yml

🗑stop_service:
  stage: 🚀deploy
  only:
    - master
  when: manual
  environment:
    name: production/${CI_PROJECT_NAME}-${CI_COMMIT_REF_SLUG}
    action: stop
  script: |
    faas-cli remove -f config.deploy.yml

# Add your project to your GitLab instance

  • You need to create an empty project named hey-people on your GitLab instance
  • Then add this environment variables in the CI/CD settings:
    • DOCKER_REGISTRY with for example, this value (this is mine): registry.test:5000
    • OPENFAAS_URL with for example, this value (this is mine): http://openfaas.test:8080
    • OPENFASS_TOKEN with : your_openfaas_token
  • add this line build to the .gitignore file
cd hey-people
git init
git remote add origin git@gitlab.bots.garden:<YOUR_GITLAB_HANDLE>/hey-people.git
git add .
git commit -m "🎉 Initial commit"
git push -u origin master

Then a new pipeline should start:

html

And you should to be able to access to your webapp from here: http://openfaas.test:8080/function/hey-people-master/ (opens new window) and your service from http://openfaas.test:8080/function/hey-people-master/hello (opens new window)

That's all folks 😃

My next blog posts should be about:

Last Articles