Skip to content
Jan Gehring edited this page Nov 29, 2015 · 8 revisions

Tomcat Deployment

To deploy an application into a Tomcat container you need to do the following steps.

Installing Tomcat

To test the deployment you can just download the current tomcat binary from the tomcat webpage and extract it into a folder: /srv/{some_project_name}/tomcat/instance01. After this you have to edit the file conf/tomcat-users.xml and add a user which is allowed to connect to tomcat manager and do deployments.

Create a directory and adding a Rexfile and a meta.yml file.

The meta.yml file.

Name: MyDeployment
Description: My Tomcat Deployment
Require:
  Project:
    git: https://github.com/RexOps/rex-project.git
    branch: master
  Application:
    git: https://github.com/RexOps/rex-application.git
    branch: master
PerlRequire:
  - Rex::Apache::Deploy

The Rexfile.

use Rex -feature => ['1.3'];

use Project;
use Application::Tomcat;

group servers => "myserver-[01..10]";

task "rollout", group => "servers", sub {
  my $project     = Project->new;
  my $application = $project->application;
  my $instance    = $application->get_deployable_instance;

  $instance->deploy_app("myapp.war" => "/myapp");
  $instance->restart;
};

Configure the application

If you need to upload some configuration files for the application you can create the folder conf and add the following line before (or after) the deploy_app method call. The configure_app method will upload all files (not recursive) inside the conf folder to the server. In this special case (Tomcat application) it will upload the files into the conf/myapp directory of your Tomcat instance.

task "rollout", group => "servers", sub {
  my $project     = Project->new;
  my $application = $project->application;
  my $instance    = $application->get_deployable_instance;

  $instance->configure_app("conf" => "myapp");   # upload local 'conf' to 
                                                 # remote 'conf/myapp' folder of 
                                                 # the tomcat instance
  $instance->deploy_app("myapp.war" => "/myapp");
  $instance->restart;
};

Running the deployment

To run the deployment you first need to resolve the dependencies:

rexify --resolve-deps

This will download every module mentioned in Require and PerlRequire. After this you can just call the rollout task.

rex rollout

How does it work?

The Project class has the ability to detect the application that is installed on the server via the registered Application classes. In this example we just load the Application::Tomcat class, so it will only check for this application type and if it found the application it will return the object that we use to get the instances and do the deployment.

The default search path for projects is /srv. This folder can be modified when you create a project instance.

my $project = Project->new(srv_root_path => "/opt");   # search for projects in /opt

After this the Project object will check which directories are inside this directory and if more than one is found it will throw an exception because it doesn't know which project you want to deploy. You can also add the right project to the object generation.

my $project = Project->new(
  srv_root_path => "/opt",    # search for projects in /opt
  name          => "myproject", # use /opt/myproject as project directory
);

After the project is loaded you can query the Project object for the applications it has. The base project object only supports one application per project. But you can easily extend the Project class to allow multiple applications if you need this.

my $application = $project->application;

If you need to deploy an application type which isn't supported yet, you can just create your own application and instance object. Usually you need to overwrite the get_instances and get_deployable_instance method in your custom application class and in your custom instance class you need to overwrite the deploy_app, start, stop and restart methods. Sometimes you also need to overwrite the configure_app method if you need to do special configurations.

The classes all uses Moose for class generation. So you can also use the before, after and around modifiers. Be aware that you don't load the Rex or Rex::Commands module directly into your Moose class because there are conflicting function exports. If you need to call functions from Rex::Commands you can do a require Rex::Commands; and call the Rex::Commands functions via its namespace for example: Rex::Commands::connection()->server.