# Building EnMasse

## Prerequisites

To build EnMasse, you need

   * [JDK](http://openjdk.java.net/) >= 1.8
   * [Apache Maven](https://maven.apache.org/) >= 3.3.1
   * [Docker](https://www.docker.com/)
   * [GNU Make](https://www.gnu.org/software/make/)
   * [Asciidoctor](https://asciidoctor.org/) >= 1.5.7

The EnMasse java and node modules are built using maven. All docker images are built using make.

## Building

### Pre-installation

*Note*: Make sure docker daemon is in running state.

#### Doing a full build, run unit tests and build docker images:

    make

This can be run at the top level or within each module. You can also run the 'build', 'test', and 'package' targets individually.
This builds all modules including java.


#### Tagging and push images to a docker registry

    export DOCKER_ORG=myorg
    export DOCKER_REGISTRY=docker.io
    #optional parameters
    export COMMIT=v.1.0.3 #for specific version of your image

    docker login -u myuser -p mypassword $DOCKER_REGISTRY

    # To generate templates to pull images from your docker hub org
    make -C templates

    make docker_tag
    make docker_push

*Note*: If you are using OpenShift and 'oc cluster up', you can push images directly to the builtin registry
by setting `DOCKER_ORG=myproject` and `DOCKER_REGISTRY=172.30.1.1:5000` instead.

#### Deploying to an OpenShift instance assuming already logged in with cluster-admin permissions

```
oc new-project myproject || oc project myproject
oc process -f templates/build/enmasse-latest/install/templates/enmasse-with-standard-authservice.yaml NAMESPACE=myproject | oc create -f -
```

#### Deploying to a Kubernetes instance assuming already logged in with cluster-admin permissions

```
kubectl create namespace myproject
kubectl config set-context $(kubectl config current-context) --namespace=myproject

mkdir -p api-server-cert
openssl req -new -x509 -batch -nodes -days 11000 -subj "/O=io.enmasse/CN=api-server.myproject.svc.cluster.local" -out api-server-cert/tls.crt -keyout api-server-cert/tls.key
kubectl create secret tls api-server-cert --cert=api-server-cert/tls.crt --key=api-server-cert/tls.key

mkdir -p standard-authservice-cert
openssl req -new -x509 -batch -nodes -days 11000 -subj "/O=io.enmasse/CN=standard-authservice.myproject.svc.cluster.local" -out standard-authservice-cert/tls.crt -keyout standard-authservice-cert/tls.key
kubectl create secret tls standard-authservice-cert --cert=standard-authservice-cert/tls.crt --key=standard-authservice-cert/tls.key

kubectl create -f templates/build/enmasse-latest/install/bundles/enmasse-with-standard-authservice
```

#### Running smoketests against a deployed instance

    make SYSTEMTEST_ARGS=SmokeTest systemtests

### Running full systemtest suite

#### Install systemtests dependencies

    ansible-playbook systemtests/ansible/playbooks/systemtests-dependencies.yml --tags clients --skip-tags dependencies

#### Running the systemtests

    make systemtests
    
#### Run single system test

    make SYSTEMTEST_ARGS="io.enmasse.systemtest.standard.QueueTest#testCreateDeleteQueue" systemtests
    
## Reference

This is a reference of the different make targets and options that can be set when building an
individual module:

#### Make targets

   * `build`        - build
   * `test`         - run tests
   * `package`      - create artifact bundle
   * `docker_build` - build docker image
   * `docker_tag`   - tag docker image
   * `docker_push`  - push docker image
   * `deploy`       - deploys the built templates to OpenShift. The images referenced by the template must be available in a docker registry
   * `systemtests`  - run systemtests

Some of these tasks can be configured using environment variables as listed below.

#### Debugging Java Code on OpenShift or Kubernetes

To enable debug mode for the Java based components, it's necessary to setup following environment variables:

   * JAVA_DEBUG - set to true to enable or false to disable
   * JAVA_DEBUG_PORT - 8787 by default and can be any value above 1000 if need to change it

Use this command to change environment variables values for the deployment

    $CMD set env deployments/<deployment-name> JAVA_DEBUG=true

Where $CMD is `oc` or `kubectl` command depends of the environment.

The following deployment names are available depending on their types and EnMasse configuration:

   * `address-space-controller`
   * `admin`
   * `api-server`
   * `keycloak-controller`
   * `standard-controller`
   * `service-broker`
   * `topic-forwarder`
   * `mqtt-gateway`
   * `mqtt-lwt`
   * `queue-scheduler`

For forwarding port from the remote pod to the local host invoke following command (it will lock terminal) and then
connect with development tool to the forwarded port on localhost

   $CMD port-forward $(oc get pods | grep <deployment-name> | awk '{print $1}') $JAVA_DEBUG_PORT:$JAVA_DEBUG_PORT

#### Environment variables

There are several environment variables that control the behavior of the build. Some of them are
only consumed by some tasks:

   * OPENSHIFT_MASTER  - URL to OpenShift master. Consumed by `deploy` and `systemtests` targets
   * OPENSHIFT_USER    - OpenShift user. Consumed by `deploy` target
   * OPENSHIFT_PASSWD  - OpenShift password. Consumed by `deploy` target
   * OPENSHIFT_TOKEN   - OpenShift token. Consumed by `systemtests` target
   * OPENSHIFT_PROJECT - OpenShift project for EnMasse. Consumed by `deploy` and `systemtests` targets
   * DOCKER_ORG        - Docker organization for EnMasse images. Consumed by `build`, `package`, `docker*` targets. tasks. Defaults to `enmasseproject`
   * DOCKER_REGISTRY   - Docker registry for EnMasse images. Consumed by `build`, `package`, `docker_tag` and `docker_push` targets. Defaults to `docker.io`
   * TAG               - Tag used as docker image tag in snapshots and in the generated templates. Consumed by `build`, `package`, `docker_tag` and `docker_push` targets.

## Debugging

### Remote Debugging

In order to remote debug an EnMasse component deployed to a pod within the cluster, you first need to enable the remote
debugging options of the runtime, and the forward port from the host to the target pod.  You then connect your IDE's
debugger to the host/port.

The instructions vary depending on whether the component is written in Java or NodeJS.  The precise steps vary by
developer tooling you use.  The below is just offered as a guide.

#### Java components

If you have a Java component running in a pod that you wish to debug, temporarily edit the deployment
(`oc edit deployment` etc.) and add the Java debug options to the standard `_JAVA_OPTIONS` environment variable to the
container.

```yaml
- env:
 - name: _JAVA_OPTIONS
   value: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
```

#### NodeJS components

If you have a NodeJS component running in a pod that you wish to debug, temporarily edit the deployment and add the
NodeJS debug option `--debug` to a `_NODE_OPTIONS` environment variable to the container.  By default, NodeJS
will listen on port 5858.

```yaml
- env:
 - name: _NODE_OPTIONS
   value: --debug
```

#### Port Forwarding

On OpenShift, you can then issue a `oc port-forward <pod> <LOCAL_PORT>:<REMOTE_PORT>` command to conveniently route
traffic to the pod's bound port.  Attach your IDE debugger the host/port.

## Hints to speed up your build/test cycle.

The build process generates license metadata which include license text files.  The latter are downloaded from the
 internet. In order to save time during your build/test cycle, turn off license artifact generation using
 `-DskipLicenseArtifactGeneration=true` on the Maven command line.  **Remember not to set this flag during release builds.**
