§Bundle configuration

ConductR has a bundle format in order for components to be described. In general there is a one-to-one correlation between a bundle and a component.

Bundles provide ConductR with some basic knowledge about components in a bundle descriptor; in particular, what is required in order to load and run a component. The following is an example of a bundle.conf descriptor:
(Typesafe configuration is used):

version               = "1"
name                  = "simple-test"
compatibility-version = "1"
tags                  = ["1.0.0-beta.1"]
system                = "simple-test"
system-version        = "1"
nr-of-cpus            = 0.1
memory                = 134217728
disk-space            = 10485760
roles                 = ["web"]
annotations           = {
  "com.mycomany.region" = "us-east"
}
components = {
  "angular-seed-play" = {
    description      = "angular-seed-play"
    file-system-type = "universal"
    start-command    = ["angular-seed-play/bin/angular-seed-play", "-Xms=67108864", "-Xmx=67108864"]
    endpoints        = {
      "angular-seed-play" = {
        protocol      = "http"
        bind-port     = 0
        service-name  = "angular-seed-play"
        acls          = [
          {
            http = {
              requests = [
                {
                  path-beg = "/"
                }
              ]
            }
          }
        ]
      }
    }
  }
}

The following table describes each property:

Name Description
acls Discussed below.
annotations A HOCON value describing any additional metadata that ConductR itself is not concerned with. Annotation keys should be namespaced as per the OCI image specification.
bind-port Discussed below.
compatibility-version A versioning scheme that will be associated with a bundle that describes the level of compatibility with the bundle that went before it. ConductR can use this property to reason about the compatibility of one bundle to another given the same bundle name. By default we take the major version component of a version as defined by http://semver.org/. However you can make this mean anything that you need it to mean in relation to the bundle produced prior to it. We take the notion of a compatibility version from http://ometer.com/parallel.html.
components Each bundle has at least one component, and generally just one. A bundle component contains all that is required to run itself in terms of its directory on disk when the bundle is expanded. This section describes the meta data required for each bundle component.
description A human readable description of the bundle component.
disk-space The amount of disk space required to host an expanded bundle and configuration.
endpoints Discussed below.
file-system-type Describes the type of the bundle and can be either “universal” or “docker”. A universal type means that this bundle copmonent will be run outside of a container. The Host environment will therefore be available, including a Java runtime. Docker types expect a Dockerfile to reside within a component. The Docker component will be built and run at the time of the bundle being run.
memory The amount of resident memory required to run the bundle. Use the Unix top command to determine this value by observing the RES and rounding up to the nearest 10MiB.
name The human readable name of the bundle. This name appears often in operational output such as the CLI.
nr-of-cpus The minimum number of cpus required to run the bundle (can be fractions thereby expressing a portion of CPU). This value is considered when starting a bundle on a node. If the specified CPUs exceeds the available CPUs on a node, then this node is not considered for scaling the bundle. Once running, the application is not restricted to the given value and tries to use all available CPUs on the node. Required.
protocol Discussed below.
roles The types of node in the cluster that this bundle can be deployed to. Defaults to “web”.
service-name Discussed below.
start-command Command line args required to start the component. Paths are expressed relative to the component’s bin folder. The default is to use the bash script in the bin folder. Arguments can be passed to a Docker container run command via a special dockerArgs command should additional args be required: start-command = ["dockerArgs","-v","/var/lib/postgresql/data:/var/lib/postgresql/data"]. See also Java memory
system The name of a cluster system that the bundle belongs to. Cluster systems are strings that may be used by a number of bundles in order to associate them. ConductR provides a guarantee that bundles belonging to the same cluster system are started with the first one in isolation to the starting of the rest. This behavior can be leverage to form clusters where the first node must form the cluster and other nodes may then join it.
system-version A version to associate with a system. This setting defaults to the value of compatibilityVersion.
tags A list of tags that may be used to provide more meaning to a bundle’s name. Just as with a name, these strings are intended for human consumption and ConductR makes no assumptions about their value - see compatibility-version for semantically relevant versioning. Tags commonly represent version numbers. Tags may be used when selecting a bundle by bundle name, and may be specified by appending a : to the name followed by the tag itself e.g. “mybundle:1.0.0-beta.1” where “1.0.0-beta.1” is the tag.
version The version of the bundle.conf file. Should be set to 1.

ConductR application bundles should not contain deployment specific configuration information such keys, passwords or secrets. Deployment target specific configuration and secrets should instead be set in a configuration bundle. The configuration bundle is deployed together with the application bundle. This enables a single application bundle to be deployed to multiple environments such test, staging and production by changing only the configuration bundle it is paired with at deployment instead of rebuilding the application bundle.

§Endpoints

Understanding endpoint declarations is important in order for your bundle to be able to become available within ConductR.

A bundle’s component may be run either within a container or on the ConductR host. In either circumstance the bind interface and bind port provided by ConductR need to be used by a component in order to successfully bind and start listening for traffic. These are made available as name_BIND_IP and name_BIND_PORT environment variables respectively (see the “Standard Environment Variables” section toward the bottom of this document for a reference to all environment variables).

Because multiple bundles may run on the same host, and that their respective components may bind to the same port, we have a means of avoiding them clash.

The following port definitions are used:

Name Description
service-port The port number to be used as the public-facing port. It is proxied to the host-port.
host-port This is not declared but is dynamically allocated if bundle is running in a container. Otherwise it has the same value as bind-port.
bind-port The port the bundle component’s application or service actually binds to. When this is 0 it will be dynamically allocated (which is the default).

Endpoints are declared using an endpoint setting using a Map of endpoint-name -> Endpoint(bindProtocol, bindPort, serviceName, acls) pairs.

The bind-port allocated to your bundle will be available as an environment variable to your component. For example, given the default settings where an endpoint named “web” is declared that has a dynamically allocated port, an environment variable named WEB_BIND_PORT will become available. WEB_BIND_IP is also available and should be used as the interface to bind to.

Service names are declared through serviceName property for each endpoint. A service name is used address the service when performing a service lookup. Resolving services describes service resolution in a greater detail.

The request acls is declared through the acls property, and allows declaration of HTTP, TCP, and UDP based endpoints. ACL configuration describes how to configure request acls in a greater detail.

§Docker Containers and ports

When your component will run within a container you may alternatively declare the bind port to be whatever it may be. Taking our Play example again, we can set the bind port with no problem of it clashing with another port given that it is run within a container:

    endpoints        = {
      "angular-seed-play" = {
        protocol      = "http"
        bind-port     = 9000
        service-name  = "angular-seed-play"
        acls          = [
          {
            http = {
              requests = [
                {
                  path-beg = "/"
                }
              ]
            }
          }
        ]
      }
    }

§Legacy & third party bundles

§When you cannot change your source

It is sometimes not possible or practical to change source code in order to signal successful startup or have it use the environment variables that ConductR provides.

We provide a CLI command named shazar for bundling the contents of any folder. You can therefore hand-craft a bundle.conf and its component folders and use shazar to bundle it.

As a quick example, suppose that you wish to bundle ActiveMQ as a Docker component with a Dockerfile. You can do something like this (btw: we appreciate that you cannot change the world in one go and don’t always have the luxury of using Akka for messaging!):

version               = "1"
name                  = "jms-docker"
compatibility-version = "1"

system         = "jms-docker"
system-version = "1"

nr-of-cpus   = 0.1
memory     = 67108864
disk-space = 10485760
roles      = ["jms"]

components = {
  "jms" = {
    description      = "A Docker container for Active/MQ"
    file-system-type = "docker"
    start-command    = []
    endpoints        = {
      "jms" = {
        bind-protocol = "tcp"
        bind-port     = 61616
        service-name  = "jms"
        acls          = [
          {
            tcp = {
              requests = [61616]
            }
          }
        ]
      }
    }
  }
  "jms-status" = {
    description      = "Status check for the jms component"
    file-system-type = "universal"
    start-command    = ["check", "docker+$JMS_HOST"]
    endpoints        = {}
  }
}

The declaration of interest is the jms-status component. ConductR provides a check command that bundle components may use to poll a tcp endpoint until it becomes available. docker instructs check to wait for all Docker components of this bundle to start and JMS_HOST is a standard environment variable that will be provided at runtime given the "jms" endpoint declaration; it is a URI describing the JMS endpoint. You can similarly poll http endpoints and wait for them to become available. Note in this examples that the check parameter docker+$JMS_HOST is specific to the endpoint jms. An endpoint of webserver would use docker+$WEBSERVER_HOST instead.

§To Docker or Not

Docker is a technology that provides containers for your application or service. Most Lightbend Reactive Platform (Lightbend RP) based programs should not require Docker as the host OS’s Java Runtime Environment 8 (JRE 8) environment should be sufficient. Bundles generally contain all that is required for a Lightbend RP program to run, with exception to the Host OS and the host JRE. Lightbend RP, and being JVM based in general, bundles will start faster and incur less system resources when used without Docker.

Docker becomes relevant when there are specific runtime dependencies that are different to ConductR’s host OS environment. In particular if a binary program that does not use the JVM is required to be launched from a bundle then it becomes more likely to benefit from using a Docker container.

For more Docker bundle options see “[Creating Bundles](Creating Bundles)”.

§Configuration Bundles

Configuration bundles are bundles containing only configuration values such as API keys and secrets. Configuration bundles are deployed together with application bundles. This keeps the configuration out of the application code and enables application bundles to be deployed to various environments without repackaging the application bundle.

To create a configuration bundle, run shazar on a directory containing a runtime-config.sh and/or bundle.conf file. The runtime-config.sh file should export any environment variables to be set. The bundle.conf file should contain any bundle key settings to be overridden. Only the values to be overridden need to be specified. Bundle key values already defined the application bundle do not need to be redefined.

For example to set an application secret and override the application’s declared role, simply create the configuration files into a directory and shazar the directory containing the files. The configuration bundle will take its name from the directory name.

mkdir test-config
echo 'export "APPLICATION_SECRET=thisismyapplicationsecret-pleasedonttellanyone"'> test-config/runtime-config.sh
echo 'roles      = [partner-frontend]' > test-config/bundle.conf
shazar test-config

The resultant bundle, i.e. test-config-2ddf3c2453ad16589b7bfae316e6ec746418491292f874b72236741bbd8f84ab.zip is then loaded together with the application.

conduct load webserver-015f73613aa48d397b0dbab6d7f96d687c56d72a275a5ea43d7da44a21c27482.zip test-config-2ddf3c2453ad16589b7bfae316e6ec746418491292f874b72236741bbd8f84ab.zip

Where webserver-015f73613aa48d397b0dbab6d7f96d687c56d72a275a5ea43d7da44a21c27482.zip is the application bundle.

Alternatively, you can also provide the configuration directory directly to conduct load if that better fits your workflow. In this case, the CLI will automatically create a configuration bundle for you.

conduct load webserver-015f73613aa48d397b0dbab6d7f96d687c56d72a275a5ea43d7da44a21c27482.zip test-config

§Configuration Bundle Files

It is also possible to include files in addition to the runtime-config.sh and/or bundle.conf file(s). To do this, create one or more files or sub folders with files alongside these files. Your runtime-config.sh script is then responsible for copying the additional files to the location that your application or service requires.

The script below demonstrates how to copy a config file to a target location.

BUNDLE_CONFIG_DIR="$( cd $( dirname "${BASH_SOURCE[0]}" ) && pwd )"
TARGET="/opt/ourApp/initConfig.cfg"

cp "${BUNDLE_CONFIG_DIR}"/someFile.cfg "${TARGET}"

If you needed to copy somewhere within the associated bundle component you could, for example:

TARGET="my-component/conf"

…where my-component/conf is the configuration folder of the associated bundle with a component named my-component.

runtime-config.sh is the name preferred by ConductR when searching for a script to execute within a configuration bundle. However you can name the configuration script anything that you like. In the case of ambiguity though, for example where you have a.sh and b.sh, ConductR does not know which is the one to select, and it can select either depending on your JDK. In most cases then, you’re better to stick with runtime-config.sh

Next: Sandbox bundle development