Spin
Spin is a groovy-based command-line tool for resource and service orchestration. It allows you to install, start, stop, uninstall and obtain the status of any spin-defined resource or service.
Installation
Prerequisites
Spin requires Java 7 or later in your $PATH
. For example, using Homebrew:
brew cask install java
If you do not use Homebrew, download and install the JDK and ensure that $JAVA_HOME
is set and that $JAVA_HOME/bin
directory is in your $PATH
. For example, in ~/.bash_profile
:
export JAVA_HOME="$(/usr/libexec/java_home)"
export PATH="$JAVA_HOME/bin:$PATH"
Install
Mac via Homebrew:
brew install lhazlewood/tap/spin
If you do not use homebrew, download and install the spin
zip package to a location you prefer. For example:
SPIN_VERSION="0.3.0"
mkdir -p ~/devtools/spin
pushd ~/devtools/spin
curl -LO "http://repo1.maven.org/maven2/com/leshazlewood/spin/spin/$SPIN_VERSION/spin-$SPIN_VERSION.zip"
unzip "spin-$SPIN_VERSION.zip"
rm -rf current && ln -s "spin-$SPIN_VERSION" current
popd
And don't forget to add the package's bin
directory to your path. For example in ~/.bash_profile
:
export SPIN_HOME="$HOME/devtools/spin/current"
export PATH="$SPIN_HOME/bin:$PATH"
Usage
Run spin help
to see options and commands:
me@myhost:~$ spin help
Usage: spin [options] <command> [<service-name>]
Options:
-h, -help, --h, --help Show help
-f <spin-config-file> Use <spin-config-file> instead of searching default file locations
-p name[,name2,name3,...] A comma-delimited list of profiles to enable
-e <environment-name> Enable environment configuration for the specified <environment-name>
-v, --version Show spin version
Commands:
help Show help
install Install all uninstalled services
install <service-name> Install the service named <service-name>
start Starts all services
start <service-name> Starts only the service named <service-name>
status Show the status of all services
status <service-name> Show the status of <service-name>
stop Stops all services
stop <service-name> Stops only the service named <service-name>
uninstall Uninstalls all installed services
uninstall <service-name> Uninstalls the service named <service-name>
Configuration
When spin executes, it will by default look for a services configuration file located in one of the following locations, in order (first one found wins):
$PWD/spin.groovy
$HOME/.spin/spin.groovy
If you want to specify a different services config (i.e. the 'context' that spin will assume), you can use the -f <spin-config-file>
option as described in the help output above. For convenience, we'll assume that you'll configure a default file.
spin.groovy
This file is a Groovy configuration file with a top-level services
block. The services
block contains one or more nested named blocks. Each nested name is the name of a service. It's associated block is a service definition. You can install, start, stop, uninstall and obtain the runtime status of a service by using its spin service name.
Here is an example config:
services {
vm {
type = 'dockerMachine'
profiles = 'all'
machine = 'dev'
driver {
name = 'virtualbox'
options {
memory = 4096
}
}
}
zookeeper {
type = 'docker'
image = 'zookeeper:3.4.7'
ports = ['2181:2181', '2888:2888', '3888:3888']
healthchecks {
ready {
command = "docker exec zookeeper /zk/bin/zkServer.sh status"
}
}
}
kafka {
type = 'docker'
dependsOn = 'zookeeper'
image = 'kafka:0.9.0.0'
ports = ['9092:9092']
links = ['zookeeper:zk']
healthchecks {
ready {
command = "docker logs --tail=15 kafka | grep ', started (kafka.server.KafkaServer)'"
}
}
}
webapp {
type = 'exejar'
artifact {
groupId = 'mycompany'
artifactId = 'mywebapp'
version = '1.2.1'
}
// instead of a maven artifact, you could specify a file path
// via the 'jar' property, for example:
//jar = 'path/to/mywebapp-1.2.1.jar'
stdout = './application.log'
options = ['-Xms256m', '-Xmx1g']
systemProperties {
'spring.main.show_banner' = false
foo = 'bar'
}
args = ['hello', 'world']
healthchecks {
ready {
command = "curl localhost:8080 -s -f -o /dev/null"
sleep = 5
}
}
}
}
The above configuration indicates there are four services defined:
- a docker-machine virtual machine named
vm
- a docker service named
zookeeper
- a docker service named
kafka
- an executable jar web application named
webapp
When interacting with spin
you can control any service using its name. For example:
spin start zookeeper
spin status zookeeper
spin stop zookeeper
You can add more services by adding more top-level service-name-to-service-definition pairs like the ones above.
Each type of service (docker, exejar, etc) has its own configuration options, and those will be covered later.
Universal Service Configuration Options
While each type of service has its own configuration options, there are a few options that are universal to any defined service:
type
The type
property is required and defines the type of plugin that will be used to execute any spin command specified for the service.
The field value is a string, and assumes a heuristic: the value is actually a lower-case version of a Groovy class file with a name that ends with 'Plugin.groovy
' and that file is present in either the following two directories:
$HOME/.spin/plugins
<spin install directory>/plugins
The above directory locations are searched in the order listed above. Once a plugin is found it is returned immediately, short-circuiting any remaining locations.
heuristic
The plugin name heuristic is as follows, using the example name docker
- Take the plugin name and uppercase the first character:
docker
-->Docker
- Take the resulting capitalized name and suffix it with Plugin.groovy:
Docker
-->DockerPlugin.groovy
- Look for a file with this name in the above listed plugin directories. Use the first one found.
This flexible nature allows you to define custom plugins as desired for any type of service. Information on creating custom plugins will be covered later.
profiles
The profiles
property is optional. It defines one or more profiles that must be enabled when running spin
(by using the -p name,name2,...
flag) in order for the service to be enabled.
The profiles property value may be either a single string value or a list of string values, e.g. ['foo', 'bar', ...]
The above example configuration specifies a profiles
value of all
:
vm {
type = 'dockerMachine'
profiles = 'all'
// etc...
}
This ensures the vm
service will only be invoked when the all
profile is enabled. For example:
spin -p all start
Similarly, running just spin start
will not interact with the vm
service.
Profiles are useful because you may not want to start and stop certain services every time you run spin
.
For example, you may want the vm
virtual machine to always be running behind the scenes while you bulk start/stop other services. This allows you to run, say, spin stop
and the other services will be stopped, but vm
will not be stopped.
Service definitions without a profiles
property will always be executed, unless they are disabled via the enabled
property. However, because profiles
allows you more options of when a plugin is enabled or not, it is usually preferred over using the enabled
property. For example, you could specify a disabled
profile, and as long as you never run spin -p disabled
, that service will not be invoked.
enabled
The enabled
property is optional and allows you to define whether or not the service will be enacted upon at all when executing spin
. It is mostly convenient for entirely disabling a service without having to comment it out or remove it from the spin configuration file.
If you set this property to false
, the corresponding service will not be invoked when executing spin.
If you set this property to true
(or do not define the property at all), the service configuration is evaluated.
Because the profiles
property supports more flexible configuration of when a service is enabled or not, it is generally recommended to use the profiles
property instead of enabled
in most cases.
dependsOn
The dependsOn
property is optional and allows you to define one or more services that should be executed first before executing the current service.
The dependsOn
property value may be either a single string value or a list of string values, e.g. ['foo', 'bar', ...]
In the above example, the kafka
service indicates that it depends on zookeeper
:
kafka {
type = 'docker'
dependsOn = 'zookeeper'
// etc...
}
Service Evaluation Order
All dependsOn
usages are evaluated to form a service Directed Acyclic Graph (DAG) (via a topological sort with Tarjan's algorithm if you're curious) to ensure correct command execution order across services.
When running spin install
, spin start
or spin status
, the install
, start
, or status
command is guaranteed to execute on required services first before executing the command on depending services. In the above example, calling spin start
ensures that start
is executed for zookeeper
first before calling start
for kafka
.
When running spin stop
or spin uninstall
, the command execution order is reversed. This ensures that required services are stopped or uninstalled after dependent services. In the above example, calling spin stop
ensures that stop
is executed for kafka
first before calling stop
for zookeeper
.
healthchecks
The healthchecks
property is optional. It allows you to specify one or more healthchecks that must pass after starting a service before the service is seen as healthy. Each defined healthcheck must successfully complete in a certain amount of time - if it does not, spin treats this as a failed startup and will exit accordingly.
If present, the healthchecks
property must be a Map
of one or more healthcheck-name (a String
) to healthcheck-definition (a Map
) pairs. For example:
services {
myservice {
// etc...
healthchecks {
ready {
command = '<shell command here>'
tries = 20
sleep = 3
}
}
}
}
This example has one healthcheck named ready
, but this name can be whatever string you want that makes sense for your healthcheck. Any number of named healthcheck definitions may be defined within healthchecks
.
A healthcheck definition may have 3 properties:
command
This is a required String, and must be a shell command (or a sequence of commands piped together). If the command/commands return(s) with an exit value of 0
(zero), then the healthcheck is considered successful, and no further tries for that particular healthcheck definition will be attempted. An early success return for one healthcheck does not impact other healthchecks in any way - all defined healthchecks for a service must pass for the service to be considered successfully started.
tries
The tries
property specifies the (integer) number of attempts the command
will be executed before giving up and indicating that the service is unhealthy and has failed to start. The first time the command executes successfully (with an exit value of zero), all subsequent attempts are skipped.
The tries
property is optional. If not specified, the default value is 20
tries.
sleep
The sleep
property specifies the (integer) number of seconds to sleep/wait after an unsuccessful healthcheck attempt before executing the next attempt.
The sleep
property is optional. If not specified, the default value is 3
seconds.
stdout
Most successful invocations of underlying service commands result in verbose output that ins't necessary when running spin
, so spin does not relay the underlying service shell command success stdout by default. However, this output could be beneficial in some cases, especially if trying to find out why a command failed for a particular service. If you want to enable stdout when running a spin command for a service, you can set this property to one of two values: either the String enabled
or a String file path.
enabled
Setting stdout
to a String value of enabled
will print out anything from the service's stdout or stderr streams directly to the same console that is running spin.
File Path
If you set the stdout
property value to a String value that is not equal to the literal values enabled
, disabled
, true
, or false
, then spin interprets this string as a File path. Spin will redirect output of the target service (stdout and stderr) to the specified file.
Plugins
The following list of plugins below are those that are available out-of-the-box when you install spin.
dockerMachine
The dockerMachine
plugin allows managing the lifecycle of a docker-machine-based virtual machine (the VM itself, not any docker containers that run inside it). It is enabled by setting the service definition's type
property to dockerMachine
(case sensitive).
The dockerMachine
plugin is a spin-specific abstraction on top of the docker-machine
executable; docker-machine
must already be installed and in your $PATH
.
An example configuration:
vm {
type = 'dockerMachine'
profiles = 'mac'
machine = 'dev'
driver {
name = 'virtualbox'
options {
memory = 4096
}
}
certs {
'docker.yourcompany.com' {
clientCert = '~/certs/client.cert'
clientKey = '~/certs/client.key'
caCert = 'http://ca.yourcompany.com/Company-Root-CA.pem'
}
}
routes = ['bridge']
}
The dockerMachine
plugin currently supports the following config properties:
certs
The certs
property allows you to specify client or CA certificates that are required when accessing one or more docker registry servers. This is helpful for organizations that have private registries and use TLS client or server (or both) TLS authentication. caCerts
is optional.
The certs
property contains one or more named blocks where each block name is the host name (and optional port) of a docker registry. The following example shows two named blocks within certs
:
// ...
certs {
'docker.yourcompany.com' {
clientCert = '~/certs/client.cert'
clientKey = '~/certs/client.key'
caCert = 'http://ca.yourcompany.com/Company-Root-CA.pem'
}
'docker2.yourcompany.com:8080' {
caCert = '~/.mycompany/ca-cert.pem'
}
}
// ...
This example indicates that two docker registries may be accessed when installing docker containers to the specified docker machine - one registry is accessible via just a host name docker.yourcompany.com
and the other registry via a hostname and port, docker2.yourcompany.com:8080
The cert files referenced within the blocks will be automatically placed in the corresponding docker machine's file system under /etc/docker/certs.d/
in a directory equal to the block name. That is, based on the example above, there will be two directories created in the respective docker machine's file system:
/etc/docker/certs.d/docker.yourcompany.com
/etc/docker/certs.d/docker2.yourcompany.com:8080
Thes are directories, not files. The files defined in each named block will be placed within these respective directories. More information on this can be found in docker's documentation on repository client certificates.
Each named block may contain 3 properties:
caCert
The caCert
property specifies the public certificate of the Certificate Authority that signed the docker registry's TLS certificate. This allows the docker client to authenticate the registry server when downloading a container.
Specifying this property is mostly only necessary when the registry server uses a TLS cert that is signed by a private certificate authority, such as one at your company/employer. If your registry server uses a TLS cert signed by a Well Known Internet certificate authority (like Digicert, Thawte, Verisign, etc), it is likely that you do not need to configure this value.
An example:
// ...
certs {
'docker.yourcompany.com' {
caCert = 'http://ca.yourcompany.com/Company-Root-CA.pem'
}
}
// ...
}
The caCert
value can be a string file path, an http
or https
URL, or even a File
instance. For example:
/fully/qualified/path/to/ca-cert.pem
$HOME/.mycompany/ca-root.pem
~/mycompany/ca.pem
http://ca.mycompany.com/root.pem
new File("wherever/ca.pem")
The source file path or URL can be named anything, but when the file is copied into the docker machine file system, it will reside at the following path and name as required by docker conventions:
/etc/docker/certs.d/{registryHost}/ca.crt
where {registryHost}
equals the registry host (i.e. block name).
Note: caCert
allows the docker client to authenticate a registry server. If that registry server requires the docker client to authenticate itself with TLS authentication, you'll need to specify the clientCert and clientKey properties as well.
clientCert
The clientCert
property specifies the public certificate that the docker client should use when authenticating itself with a docker registry server. If the docker registry server requires TLS authentication, this property will be required when the docker client attempts to download a docker container.
If the docker registry server does not require the docker client to authenticate itself, you do not need to specify clientCert
or clientKey
. But if you specify clientCert
, you must also specify the clientKey property.
For example:
// ...
certs {
'docker.yourcompany.com' {
clientCert = '~/mycompany/client.cert'
clientKey = '~/mycompany/client.private.key'
}
}
// ...
}
The clientCert
value can be a string file path, an http
or https
URL, or even a File
instance. For example:
/fully/qualified/path/to/ca-cert.pem
$HOME/.mycompany/ca-root.pem
https://company.com/myclient/client.cert
~/mycompany/ca.pem
new File("wherever/ca.pem")
The source file path or URL can be named anything, but when the file is copied into the docker machine file system, it will reside at the following path and name as required by docker conventions:
/etc/docker/certs.d/{registryHost}/client.cert
where {registryHost}
equals the registry host (i.e. block name).
clientKey
The clientKey
property specifies the private key that the docker client should use when authenticating itself with a docker registry server. If the docker registry server requires TLS authentication, this property will be required when the docker client attempts to download a docker container.
If the docker registry server does not require the docker client to authenticate itself, you do not need to specify clientKey
or clientCert
. But if you specify clientKey
, you must also specify the clientCert property.
For example:
For example:
// ...
certs {
'docker.yourcompany.com' {
clientCert = '~/mycompany/client.cert'
clientKey = '~/mycompany/client.private.key'
}
}
// ...
}
The clientKey
value can be a string file path, an http
or https
URL, or even a File
instance. For example:
/fully/qualified/path/to/client.private.key
$HOME/.mycompany/.certs/client-private.key
~/mycompany/client.cert
new File("wherever/client.cert")
The source file path or URL can be named anything, but when the file is copied into the docker machine file system, it will reside at the following path and name as required by docker conventions:
/etc/docker/certs.d/{registryHost}/client.key
where {registryHost}
equals the registry host (i.e. block name).
driver
The driver
property is a map that specifies the driver to use when creating the virtual machine. The map may contain the following properties:
name
The driver name
property specifies the docker-machine driver name to use when creating the virtual machine. The above example configuration example specifies that the virtualbox
driver should be used.
options
The driver options
property is a set of driver-specific name/value pairs to supply to the driver when creating the virtual machine. The above configuration example specifies that the virtualbox
driver should use 4096
megs of ram when creating the virtual machine.
The options specified here are applied to the docker-machine create
command using the standard docker-machine --drivername-optionname-optionvalue flag convention on the command line. This implies that the above configuration example adds the following to the docker- machine create command:
--virtualbox-memory 4096
machine
The machine
property is required. The value is the name of the docker machine to use when executing docker-machine
.
routes
The routes
property can be a single string or a list-of-strings. It is optional.
NOTE: If this property is non-null, sudo is required to modify the local operating system's routing table. Spin will prompt for the sudo password when required.
spin start
When the docker host is started via spin start
, spin will prompt for the sudo password and then automatically create routing table entries in the local operating system to the named docker networks within the docker host.
For example, assume that the routes
value equals bridge
, the docker default network. When the docker host is started via spin start
, the dockerMachine
plugin will:
- Discover the docker
bridge
network's subnet (by runningdocker network inspect bridge
, inspecting the resulting JSON, and using the[0].IPAM.Config[0].Subnet
value). For example:172.17.0.0/16
- Discover the docker host's IP address (by running
docker ip
machine, where machine is the value of the spinmachine
config property listed above). For example:192.168.99.100
- Add a route to the local operating system to ensure packets intended for the named network are routed to the docker host (which acts as a gateway for that network). For example:
route -n add 172.17.0.0/16 192.168.99.100
This ensures that any packets sent by the local operating system to a specified subnet will automatically be routed to the docker host's assigned IP address. The above example means packets destined for 172.17.0.0/16
will be routed to 192.168.99.100
, whereby the docker host will then likely route those packets to a target docker container.
Routes are created for each specified docker network name to ensure each network is routable.
spin stop
When using spin to stop the docker host via spin stop
, all routes for each named docker network are automatically removed from the local operating system routing table.
docker
The docker plugin manages the lifecycle of a single docker container. It is enabled by setting the service definition's type
property to docker
. The docker plugin automatically sets the -d
and –name
serviceName
flags when invoking docker run
to ensure the docker container runs as background service and is accessible/queryable by using the spin service name, respectively.
An example configuration:
cassandra1 {
type = 'docker'
dependsOn = 'vm'
image = 'cassandra:2'
ports = ['9160:9160', '9042:9042', '7199:7199', '7001:7001', '7000:7000']
environment {
CASSANDRA_START_RPC = true
}
healthchecks {
ready {
command = "docker exec cassandra1 /usr/bin/cqlsh -e 'describe KEYSPACES' | grep system"
}
}
}
cassandra2 {
type = 'docker'
dependsOn = 'cassandra1'
image = 'cassandra:2'
links = ['cassandra1:cassandra']
environment {
CASSANDRA_START_RPC = true
}
healthchecks {
ready {
command = "docker exec cassandra2 /usr/bin/cqlsh -e 'describe KEYSPACES' | grep system"
}
}
}
The docker plugin supports the following configuration options:
- cpu_shares
- dns
- dns_search
- environment
- hostname
- image
- links
- memory
- memory_reservation
- memory_swap
- memory_swappiness
- options
- ports
- ulimits
- volumes
- volumes_from
Any docker options not listed here (not directly supported by spin yet) can be easily supported by using the options property.
cpu_shares
The cpu_shares
property is an optional integer that specifies the 'weight' or portion of CPU cycles the container should be able to utilize relative to other containers.
See the docker cpu constraints docs for more info.
dns
The dns
property is an optional list of DNS server IP addresses that should be placed in the container's /etc/resolv.conf
file. Processes in the container, when confronted with a hostname not in /etc/hosts
, will connect to these IP addresses on port 53 looking for name resolution services.
See Docker's container DNS documentation for more.
dns_search
The dns_search
property is an optional list of domain names that are searched when a bare unqualified host name is used inside the container, by writing search
lines into the container's /etc/resolv.conf
file. For example, when a container process attempts to access host
and the search domain example.com
is set, the DNS logic will not only look up host
but also host.example.com
.
See Docker's container DNS documentation for more.
environment
The environment
property is optional. If specified, it must be either a list or a map of environment variables to expose to the docker container.
hostname
The hostname
property is optional. It allows you to set the docker container hostname.
image
The image
property is required. The value is the name of the docker image name or id (and optionally the image version number) to use when creating the docker container.
Some example image values:
image = 'ubuntu'
image = 'orchardup/postgresql'
image = 'a4bc65fd'
links
The links
property is optional. It is an array of strings. It allows you to link a container to other containers in another service. Either specify both the service name and the link alias (SERVICE:ALIAS
), or just the service name (which will also be used for the alias). Example:
links = ['db', 'db:database', 'hazelcast']
An entry with the alias’s name will be created in /etc/hosts
inside containers for this service, e.g:
172.17.2.186 db
172.17.2.186 database
172.17.2.187 hazelcast
Environment variables will also be created - see the docker environment variable reference for details.
memory
The memory
property is an optional string that indicates the maximum amount of memory that a container can use. If you set this option, the minimum allowed value is 4m
(4 megabytes).
For example:
memory = '1g' //1 gigabyte
See the docker memory constraints docs for more.
memory_reservation
The memory_reservation
property is an optional string that allows you to set a soft limit smaller than memory
which is activated when Docker detects contention or low memory on the host machine. If you use memory_reservation
, it must be set lower than memory
in order for it to take precedence. Because it is a soft limit, it does not guarantee that the container will not exceed the limit.
For example:
memory_reservation = '900m' //900 megabytes
See the docker memory constraints docs for more.
memory_swap
The memory_swap
property is an optional string that indicates the amount of memory that a container is allowed to swap to disk. See the docker memory swap docs for more.
memory_swappiness
The memory_swappiness
property is an optional integer between 0 and 100 that indicates the percentage of a container's anonymous pages the host kernel can swap. See the docker memory swappiness docs for more.
options
The options
property is an optional convenience/catch-all list-of-strings property that allows you to specify any additional options that are not already supported by the spin docker config properties.
It allows you to still use a docker run option if the spin docker plugin does not yet support it via .groovy config. Each value in the list is appended directly to the docker run
command without modification.
For example:
options [
'--an-option avalue',
'--another-option anotherValue'
]
The above would result in a docker run command that looks like this (truncated for brevity):
docker run --detach --name namehere ...etc... --an-option avalue --another-option anotherValue ...
As you can see the list values are added directly, unmodified, to the docker run command.
ports
The ports
property is optional. It is a list of container ports (as Strings) to expose. Either specify both ports (HOST:CONTAINER
), or just the container port (and a random host port will be chosen).
Example port declaration:
ports = [
'3000',
'3000-3005',
'8000:8000',
'9090-9091:8080-8081',
'49100:22',
'127.0.0.1:8001:8001',
'127.0.0.1:5000-5010:5000-5010'
]
ulimits
The ulimits
property is optional. It allows you to override a container's default ulimits. You can either specify a single limit as an integer or soft/hard limits as a mapping. For example:
ulimits = 65535
// this is the same as the following:
// ulimits {
// nproc = 65535
// }
or
ulimits {
nproc = 65535
nofile {
soft = 20000
hard = 40000
}
}
Also see the docker run --ulimit flag documentation for more.
volumes
The volumes
property allows you to mount paths as volumes, optionally specifying a path on the host machine (HOST:CONTAINER
), or an access mode (HOST:CONTAINER:ro
). Example:
volumes = [
'/var/lib/mysql',
'./cache:/tmp/cache',
'~/configs:/etc/configs/:ro'
]
For more information see the docker run -v flag documentation and the general Docker Volumes documentation.
volumes_from
The volumes_from
property is an optional list of container names or ids that have shared volumes that should be mounted in the current container.
For example:
volumes_from = ['aDataContainer', 'anotherDataContainer']
See the data volume containers docs for more information.
exejar
The exejar plugin allows you to execute and run an executable jar as a system service. It is enabled by setting the service definition's type
value to exejar
Service definition example:
webapp {
type = 'exejar'
artifact {
groupId = 'mycompany'
artifactId = 'mywebapp'
version = '1'
}
// instead of a maven artifact, you could specify a file path
// via the 'jar' property, for example:
//jar = 'path/to/jar/file'
stdout = './application.log'
options = ['-Xms256m', '-Xmx1g']
systemProperties {
'spring.main.show_banner' = false
foo = 'bar'
}
args = ['hello', 'world']
healthchecks {
ready {
command = "curl localhost:8080 -s -f -o /dev/null"
sleep = 5
}
}
}
When spin start
is called for this definition, spin will execute the following Java command and turn it into a background service:
java -Xms256m -Xmx1g -Dspring.main.show_banner=false -Dfoo=bar -jar mywebapp-1.jar hello world
In addition to the universal configuration properties, the following additional properties are supported:
args
args
is an optional array of program arguments to supply to the executable jar itself. These args will be passed to the jar's designated public static void main(String[] args)
method.
For example, the following config:
webapp {
artifact {
groupId = 'foo'
artifactId = 'bar'
version = '0.1.0'
}
args = ['hello', 'world']
}
will result in the following Java command being executed (args
in bold):
java -jar bar-0.1.0.jar
hello world
Program (main
method) arguments for the executable jar are declared after the referenced jar name. Options to the java command itself (for the JVM) come before the -jar
flag. These options can be defined as options
and systemProperties
declarations, covered below.
artifact
artifact
is a map that contains valid Maven groupId
, artifactId
and version
values of the .jar you want to execute.
Spin will use this metadata, and, under the hood, use the Maven Dependency Plugin to auto-download the specified .jar from an appropriate Maven repository server (assumes you have $HOME/.m2/settings.xml
setup correctly).
Either the artifact
or the jar
property must be specified.
jar
jar
is a File
or a String
path that reflects the executable jar location on the file system. The specified file must exist, must be a file (not a directory) and must end with the name '.jar'.
Either the jar
or the artifact
property must be specified.
options
options
is an optional array of values to add as arguments to the java
command before the -jar
flag. You may find the available options by running the java
command on the command line and looking at the resulting list of options (for example -Xmx
options or -version
etc).
An example service definition with options:
webapp {
artifact {
groupId = 'foo'
artifactId = 'bar'
version = '0.1.0'
}
options = ['-Xms256m', '-Xmx1g']
}
this definition will result in the following Java command being executed (options in bold):
java
-Xms256m -Xmx1g
-jar bar-0.1.0.jar
systemProperties
systemProperties
is optional. Each name: value
pair defined in this map will automatically be appended as -Dname="value"
system property declarations in the java options
list above.
This is a convenience property - identical behavior can be achieved by using options
alone. For example, the following two exejava
nested declarations achieve the exact same effect:
Using systemProperties
:
// ...
systemProperties {
foo = 'bar'
hello = 'world'
}
Using options
:
// ...
options = [
'-Dfoo=bar',
'-Dhello=world'
]
Even though both are effectively the same thing, defining many -D
pairs in opts can be cumbersome and perhaps more difficult to read and understand.
workingDir
The workingDir
property is optional, and if specified, must be a File
or a String
path that reflects a directory on the file system.
If specified, the java process will be launched in that directory; it is the location that will be returned if the process calls System.getProperty("user.dir");
If not specified, the current working directory when executing spin will be used, i.e. $PWD