Vortex is a virtual machine management tool. It is similar to Vagrant. The rationale for writing this tool is to enable better management of development and production infrastructure at the same time. We, Websecurify, could not easily achieve this with Vagrant so the this tool was written to fill the gap.

You can do the following things with Vortex:

Develop your application in a replicable dev environment.

Easily manage your application in the same configuration into a prod environment.

Vortex removes any barriers from the time you start developing your application to the time it is already live and you need to maintain it.

It is essential to understand the key principle behind Vortex, which is to always produce a replicable environment. This sounds nice and simple but it gets deeper than this.

What this means in practice is that virtual machines/nodes are disposable. In other words, they only exist fully provisioned and not in any other way. They also don't maintain any state. Once you halt a node, it is gone for good with all the data it was keeping within it. If you boot the node again it will launch a brand new instance. This is why there is no state.

State is essentially a 3rd-class citizen in Vortex. You provide it only by attaching external storages or by integrating with other services from your application. This sounds like a very extreme way of dealing with things but it does solve a few hard problems like scalability and the application effectiveness against hardware and other types of failure.

This philosophy is a constrain, which works in our favour and it is fully embraced in the design of the tool.

Vortex supports different providers to manage your virtual machines/nodes. Out of the box you have support for VirtualBox and Amazon. VirtualBox is the default provider. Here is an example how to select a different provider:

vortex --provider=Amazon boot # boots nodes into amazon ec2

The default provisioner, Roost, can also be configured with some command-line options. If you specify the -d|--dry flag the provisioner will only output information on what it will do but not perform any actions. This is useful if you are uncertain about the changes you are making to the roost manifests and you just want to check it out before doing it for real. For example:

The Vortex manifest file is a simple JSON document. By default you are only required to specify the nodes you want in your configuration:

{
...
"nodes": {
"my-node": {
}
},
...
}

This is the simplest possible configuration, which is not useful for anything just yet. To make this configuration useful for booting an image in Amazon you need to supply additional information. This is how it is done:

Last but not least, nodes can be launched in their own namespaces. Namespaces are useful when there are a lot of stuff going on and you just want to logically separate nodes into different groups (or soft-groups if you prefer). Here is an example:

Vortex comes with a built-in provisioner called roost - another project of ours. Roost manifest files can be either imported from an external file or embedded directly into your vortex manifest. Here is an example:

As a matter of fact, you can even apply a global roost file for all nodes. Just register the roost configuration outside of the nodes property.

Merging roost manifests is also possible when declared at multiple levels. For example, at top level you may want to apply some defaults and maybe even some updates. Per node you may want to apply generic configurations and have some additional provisioning options for each provider. Such complex setup is possible and here is an example:

Vortex can be extended with plugins. Plugins are essentially nodejs modules and are installed the same way you typically install nodejs modules, i.e. npm and package.json. A good starting doc how npm modules work can be found here.

In order to load a plugin you need to declare it in your Vortex manifest file. Here is an example:

{
...
"plugins": [
"my-plugin"
],
...
}

Plugins are executed first and can affect everything from the actual manifest that was loaded to what providers and actions are exposed and much more.

The following workflow takes place when working with plugins.

Each plugin is loaded via node's require.

The module is inspected for two functions getVortex (takes priority) and vortex.

getVortex is used to retrieve an object that exposes a vortex function.

vortex is looked for to check if the plugin is compatible at this stage.

Before execution the plugin is invoked via a call to vortex function. The following parameters are passed:

opt - command line options

manifest - the manifest file

provider - default provider

action - the action to be executed

Use getVortex to augment the Vortex environment such as install new actions, providers, etc. Use vortex to do something, mostly with the manifest file, before the actual action takes place.

Vortex plugins can do pretty much everything so here are some suggestions of what you could do if you spend some time writing a plugin:

A plugin, which fetches access credentials such as keys, usernames and password from a centralized storage.

A plugin, which adds another provisioner such as chef and puppet.

A plugin, which allows you extensive use of environment variables to configure all aspects of the manifest file.

A plugin, which double-checks all options before launching an action in order to prevent unexpected behaviour.