Skip to content

3. Rest API server

Alex Levshin edited this page Apr 27, 2017 · 21 revisions

Getting started

Rest API server is part of the Workty platform for accessing its functionality via the http/https protocols (the recommended default protocol is https). The server is implemented on the basis of the Restify framework. The server features are as follows:

  • Managing the execution of workflows
  • Managing user permissions policies (ACL) to differentiate access
  • Synchronization with Supervisor server

How To Install

Like Supervisor, this server can be run under the control of Phusion Passenger, utilities forever, etc. The main difference is that for balancing of loading you can run multiple copies of servers, Rest API fully supports the stateless paradigm.

  • Prerequirements

Before you begin, read the Database section. If you have already installed the database, you can proceed to install the Rest API server. Here is the list of utilities needed to get started:

Server settings are contained in the config.js file in the root folder of the restapi object. Let's take a closer look at each parameter:

restapi: {
       protocol: 'https', host: '127.0.0.1', port: 9999, errorLinkUrl: 'https://127.0.0.1/workty/docs/errors/api', name: 'restify api server',
       throttleConfig: { burst: 10, rate: 1000000 },
       getConnectionString: function() {
           return this.protocol + '://' + this.host + ':' + this.port;
       },
       versions: [
           {
               major: 1,
               sub: ['2016.10.1']
           }
       ],
       getLatestVersion: function() {
           if (this.versions.length === 0) {
               return null;
           }

           var latestVersion = {};

           _.forEach(this.versions, function _onEachVersion(version) {
               if (latestVersion.major) {
                   if (latestVersion.major < version.major) {
                       latestVersion.major = version.major;
                   }
               } else {
                   latestVersion.major = version.major;
               }

               _.forEach(version.sub, function _onEachSubVersion(subVersion) {
                   var subVersionParts = subVersion.split('.');
                   var subVersionDate = new Date(subVersionParts[0], subVersionParts[1], subVersionParts[2]);

                   if (latestVersion.sub) {
                       var currentSubVersionParts = latestVersion.sub.split('.');
                       var currentSubVersionDate = new Date(currentSubVersionParts[0], currentSubVersionParts[1], currentSubVersionParts[2]);
                       if (currentSubVersionDate < subVersionDate) {
                           latestVersion.sub = subVersion;
                       }
                   } else {
                       latestVersion.sub = subVersion;
                   }
               });
           });

           return latestVersion;
       }
   }
  • protocol The protocol of interaction with the rest api client can take the values ​​http or https. Default value https

  • host The name of the host on which the server is started. Default value 127.0.0.1

  • port The port number on which the server is started. Default value 9999

  • errorLinkUrl The url path, indicating the error decoding when working with rest api. Default value https://127.0.0.1/workty/docs/errors/api

  • throttleConfig.burst The internal setting of Restify. The amount of requests to burst to. Default value 10

  • throttleConfig.rate The internal setting of Restify. Steady state number of requests/second to allow. Default value 1000000

  • versions Implementing the versioning support mechanism for rest api, the client must itself control the transmission of these parameters if it needs access to another version of rest api. Currently supports only one major version 1 with subversion 2016.10.1

    • Standalone

To start the server in this mode, you must first install the node libraries from the api directory:

npm install

After successfully installing the libraries, you can run the server itself:

node -max-old-space-size=1024 --expose-gc ./api/app.js --dbhostname=127.0.0.1 --dbname=workty --major_version=1 --root_folder=/opt/workty

If successful, you will see the following messages in the console:

[2017-04-17T09:57:05.260Z] [rest] 'Workty Rest API v.1 2016.10.1 server listening at https://[::]:9999'
[2017-04-17T09:57:05.285Z] [rest] 'Connected to 127.0.0.1/workty database successfully'

Important! The Supervisor server can be started both before and after the startup of Rest API server. After successfully connecting to the Supervisor server via the websocket protocol, you will see the corresponding entry in the Rest API console of the server. Now the Rest API server is online and ready to work. The protocol of exchange with the Supervisor server is described in the file shared/protocols/v1/restapi-sv.module.js.

Now let's look at the input parameters:

  • max-old-space-size Настройка для движка V8 that hitting the maximum memory limits in Mb. Optional. Default value 1024

  • expose-gc Setting for the engine V8 which will allow you to run GC from your code. Optional

  • nouse-idle-notification Setting for the engine движка V8 which prevents running GC constantly. Optional

  • dbhostname The name of the host where the MongoDB database is installed, to which the server is connected. Required. Default value 127.0.0.1

  • dbname The name of the MongoDB database to which the server is connected. Required. Default value workty

  • major_version The major version of Rest API, currently only version 1 is supported. Optional. Default value 1

  • root_folder The root folder of the Workty project (not the Rest API server!). Required. Default value /opt/workty

    • Docker

The server also supports starting the server from the docker image, the Dockerfile file can be found in the api/deployment/dockerfiles/x64 folder (version nodejs 4.4.0 is supported). Important! When you start the docker container, you must correctly specify the mapping port for the server, which must match the one specified in config.js. By default, the value of this port is 9999, if you want to change it, change the value of the line in Dockerfile:

EXPOSE 9999

Before building docker image I recommend using the script located on the api/deployment/gulpfile.js path to create a zip archive with all the necessary files, including Dockerfile. The command to run the gulp script:

gulp --color --gulpfile ./api/deployment/gulpfile.js --build_version=1.0.0 --arch=x64 --branch_type=dev --outputlocaldir=/opt/workty-restapi-app

Let's look at the input parameters:

  • build_version The build number. Required. Default value 1.0.0
  • arch The architecture type of the processor, only the x64 value supports the script. Required. Default value x64
  • branch_type The name of the branch for the build type dev or prod. Required. Default value dev
  • outputlocaldir The name of the output folder for the zip archive. Required

After a successful build, you will find the zip archive along the path for the default values ​​/opt/workty-restapi-app/dev/x64/1.0.0/workty-restapi-app-dev-x64-1.0.0.zip. You can unzip it and build the docker image:

docker build -t alexlevshin/workty-restapi-amd64:latest .

Also you can download the docker image with the preinstalled supervisor server from docker hub:

docker pull alexlevshin/workty-restapi-amd64

And run it:

docker run -d -p 9999 alexlevshin/workty-restapi-amd64
  • Ansible

Ansible is a great utility for automating processes. In this section, I use it to automate the deployment of all parts of the system, in particular the supervisor server. In my example, the teamcity + ansible pair is used, so you need to download the plugin TC Ansible runner . All the necessary files are located in the api/ansible/x64 folder. Let's review them in detail:

inventory

[restapi-x64-stpete1]
192.168.2.254

[restapi-x64-stpete1:vars]
ports_range=9999

[all:vars]
ansible_connection=ssh
ansible_user=wt_restapi
ansible_ssh_pass=wt_restapi

By default, credentials wt_restapi/wt_restapi are used to access ssh on the machine 192.168.2.254, on which the server will be installed. Create an account with such values ​​and allow to connect via ssh.

run-latest-docker-image.yml

---
- hosts: all
  gather_facts: yes
  tasks:
  - name: Login private registry '{{  docker_private_registry_host }}'
    docker_login:
      registry: '{{ docker_private_registry_host }}'
      username: '{{ docker_private_registry_username }}'
      password: '{{ docker_private_registry_password }}'
      email: pi@workty.com

  - name: Find all running containers
    shell: docker ps | awk '{ print $0 }' | sed -n 'p' | grep -o "{{ docker_private_registry_imageprefixname }}-[^*]*" | awk '{ print $1 }'
    register: running_containers_names

  - name: Stop the running containers
    shell: docker stop {{ item }}
    with_items:
     - "{{ running_containers_names.stdout_lines }}"
    ignore_errors: True

  - name: Remove the containers
    shell: docker rm {{ item }}
    with_items:
     - "{{ running_containers_names.stdout_lines }}"
    ignore_errors: True

  - name: Run the new container '{{ docker_private_registry_imagename }}'
    docker:
      name: '{{ docker_private_registry_imageprefixname }}-{{ docker_private_registry_image_version }}'
      image: '{{  docker_private_registry_host }}/{{ docker_private_registry_username }}/{{ docker_private_registry_imagename }}'
      pull: always
      net: host
      state: reloaded
      restart_policy: unless-stopped
      ports:
       - '{{ ports_range }}:{{ ports_range }}'
      env:
         SERVICE_TAGS: ["{{ ansible_default_ipv4.address }}", '{{ docker_private_registry_image_version }}', "{{ ansible_lsb }}"]
         SERVICE_NAME: "{{ ansible_hostname }}-x64-{{ docker_private_registry_short_imageprefixname }}-{{ docker_private_registry_branch_type }}-{{ docker_private_registry_image_version }}"
         RESTAPI_DBNAME: "{{ db_name }}"
         RESTAPI_DBHOST: "{{ db_hostname }}"

This file uses a private docker repository to store docker images. A list of all variables enclosed in {{}} is passed to the ansible-playbook script via the command line:

-vvvv --extra-vars "{'docker_private_registry_host':'192.168.2.1:5000', 'docker_private_registry_username':'pi', 'docker_private_registry_password':'pi', 'docker_private_registry_imagename':'workty-restapi-app-dev-x64:1.0.0', 'docker_private_registry_imageprefixname': 'workty-supervisor-app-dev-x64', 'docker_private_registry_branch_type':'dev', 'docker_private_registry_image_version':'1.0.0', 'db_hostname': '127.0.0.1', 'db_name': 'workty', 'docker_private_registry_short_imageprefixname': 'workty-restapi-app'}"

If necessary, you can parameterize these values, in teamcity, via the Build Configuration Settings -> Parameters tab. Important! Note the two environment variables RESTAPI_DBHOST and RESTAPI_DBNAME, if you wish, you can use these values ​​in the Dockerfile file as follows:

CMD node /opt/workty-restapi-app/app.js --dbname=${RESTAPI_DBNAME} --dbhostname=${RESTAPI_DBHOST}

API Documentation

See Rest API documentation

Examples

See Tests section.