tomcatmanager

tomcatmanager is a command line tool and python library for managing a Tomcat server.

What Can It Do?

This package installs a command line utility called tomcat-manager. It’s easily scriptable using your favorite shell:

$ tomcat-manager --user=ace --password=newenglandclamchowder \
http://localhost:8080/manager deploy local sample.war /sampleapp
$ echo $?
0

There is also an interactive mode:

$ tomcat-manager
tomcat-manager>connect http://localhost:8080/manager ace newenglandclamchowder
--connected to http://localhost:8080/manager as ace
tomcat-manager>list
Path                     Status  Sessions Directory
------------------------ ------- -------- ------------------------------------
/                        running        0 ROOT
/sampleapp               stopped        0 sampleapp##9
/sampleapp               running        0 sampleapp##8
/host-manager            running        0 /usr/share/tomcat8-admin/host-manage
/manager                 running        0 /usr/share/tomcat8-admin/manager

And for the ultimate in flexibility, you can use the python package directly:

>>> import tomcatmanager as tm
>>> tomcat = tm.TomcatManager()
>>> r = tomcat.connect(url="http://localhost:8080/manager",
... user="ace", password="newenglandclamchowder")
>>> tomcat.is_connected
True
>>> r = tomcat.stop("/someapp")
>>> r.status_code == tm.StatusCode.OK
False
>>> r.status_message
'No context exists named /someapp'

The following capabilites are supported from interactive use, the Command Line, and from python:

  • deploy - deploy a war file containing a tomcat application in the tomcat server

  • redeploy - remove the application currently installed at a given path and install a new war file there

  • undeploy - remove an application from the tomcat server

  • start - start a tomcat application that has been deployed but isn’t running

  • stop - stop a tomcat application and leave it deployed on the server

  • reload - stop and start a tomcat application

  • sessions - show active sessions for a particular tomcat application

  • expire - expire idle sessions

  • list - show all installed applications

  • serverinfo - show information about the server, including tomcat version, OS version and architecture, and jvm version

  • status - show server status information in xml format

  • vminfo - show diagnostic information about the jvm

  • threaddump - show a jvm thread dump

  • resources - show the global jdni resources configured in tomcat

  • findleakers - show tomcat applications that leak memory

  • sslconnectorciphers - show tls ciphers configured for each connector

  • sslconnectorcerts - show tls certificate chain for each virtual host

  • sslconnectortrustedcerts - show trusted certificates for each virtual host

  • sslreload - reload tls certificate and key files

Table of Contents

Installation

System Requirements

You’ll need Python 3.8 or higher on macOS, Windows, or Linux.

The following Tomcat versions are supported:

  • 8.5.x

  • 9.0.x

  • 10.0.x

  • 10.1.x

The operating system and Java Virtual Machine don’t matter as long as Tomcat runs on it.

You can double check the list of versions supported by:

$ tomcat-manager -v
7.0.0 (works with Tomcat >= 8.5 and <= 10.1)

or:

$ tomcat-manager
tomcat-manager> version
7.0.0 (works with Tomcat >= 8.5 and <= 10.1)

These tools should work with newer versions of Tomcat than the ones officially supported. The Tomcat Manager web application that is part of Tomcat has been remarkably stable over many versions, with only a few additions.

Install using pip

Install using pip:

$ pip install tomcatmanager

Works on Windows, macOS, and Linux.

Now what?

First you will need to Configure Tomcat.

If you are in a hurry to get started with the command line tool, type:

$ tomcat-manager -h

Or, you can start writing your own python code which imports the package.

Configure Tomcat

This library and associated tools do their work via the Tomcat Manager web application included in the Tomcat distribution. This section describes a simple, minimal server configuration to provide authentication, but does not cover the many other ways to deploy and configure Tomcat. See Authentication for a full description of the many ways this library and associated tools can be used to authenticate to Tomcat, no matter how it is configured.

You will need the URL where the Tomcat Manager application is available. You can use the URL that points directly to the container, or the URL of a proxy like nginx or Apache HTTP Server you have deployed in front of Tomcat. TLS is recommended, but it works without if you must.

You will also need to configure authentication for a user, and grant that user permission to access the Tomcat Manager application. The full details of this procedure can be found in the Tomcat Manager Howto. A short summary is included here.

Configure a user in tomcat-users.xml and grant that user the manager-script role. The username and password can be anything of your choosing. Here’s how to configure the user we will use as an example throughout this documentation:

<tomcat-users>
    ...
    <role rolename="manager-script"/>
    <user username="ace" password="newenglandclamchowder" roles="manager-script"/>
    ...
</tomcat-users>

Interactive Use

Using the interactive command line program tomcat-manager.

tomcat-manager

Launching

After installation, you will have a new tool available called tomcat-manager. Run it with no command line arguments to invoke an interactive, line-oriented command interpreter:

$ tomcat-manager
tomcat-manager> connect http://localhost:8080/manager ace newenglandclamchowder
--connecting... [==  ]
--connected to http://localhost:8080/manager as ace
--tomcat version: [Apache Tomcat/10.1.0]
tomcat-manager> list
--listing applications... [==  ]
--Listed applications for virtual host [localhost]
Path                     Status  Sessions Directory
------------------------ ------- -------- ------------------------------------
/                        running        0 ROOT
/manager                 running       14 /usr/share/tomcat7-admin/manager
/host-manager            running        0 /usr/share/tomcat7-admin/host-manager
tomcat-manager> exit

Use the exit or quit command to exit the interpreter and return to your operating system shell.

$ tomcat-manager [url] list
Available Commands

The interactive shell has a built-in list of all available commands:

tomcat-manager> help
tomcat-manager is a command line tool for managing a Tomcat server

Type 'help [command]' for help on any command.

Here's a categorized list of all available commands:

Connecting to a Tomcat server
────────────────────────────────────────────────────────────────────────
connect      connect to a tomcat manager instance
which        show the url of the tomcat server you are connected to
disconnect   disconnect from a tomcat manager instance

Managing applications
────────────────────────────────────────────────────────────────────────
list       show all installed tomcat applications
deploy     deploy an application to the tomcat server
redeploy   undeploy then deploy an application to the tomcat server
undeploy   remove an application from the tomcat server
start      start a deployed tomcat application that isn't running
stop       stop a tomcat application and leave it deployed on the server
restart    stop and start a tomcat application
    reload   synonym for 'restart'
sessions   show active sessions for a tomcat application
expire     expire idle sessions

Server information
────────────────────────────────────────────────────────────────────────
findleakers   show tomcat applications that leak memory
resources     show global JNDI resources configured in tomcat
serverinfo    show information about the tomcat server
status        show server status information in xml format
threaddump    show a jvm thread dump
vminfo        show diagnostic information about the jvm

TLS configuration
────────────────────────────────────────────────────────────────────────
sslconnectorciphers        show SSL/TLS ciphers configured for each connector
sslconnectorcerts          show SSL/TLS certificate chain for each connector
sslconnectortrustedcerts   show SSL/TLS trusted certificates for each connector
sslreload                  reload SSL/TLS certificates and keys

Settings, configuration, and tools
────────────────────────────────────────────────────────────────────────
config         edit or show the location of the user configuration file
edit           edit a file in the preferred text editor
exit_code      show a number indicating the status of the previous command
history        view, run, edit, and save previously entered commands
py             run an interactive python shell
run_pyscript   run a file containing a python script
settings       display program settings
set            change a program setting
shell          execute a command in the operating system shell
shortcuts      show shortcuts for other commands
theme          manage themes

Other
────────────────────────────────────────────────────────────────────────
exit      exit the interactive command prompt
    quit    synonym for the 'exit' command
help      show available commands, or help on a specific command
version   show the version number of this program
license   show the software license for this program

As well as help for each command. Help for every command is avaialble in two ways:

tomcat-manager> help connect

Or:

tomcat-manager> connect -h

Here’s some examples:

tomcat-manager> help stop
usage: stop [-h] [-v VERSION] path

Stop a running tomcat application and leave it deployed on the server.

positional arguments:
    path                  The path part of the URL where the application is
                        deployed.

optional arguments:
    -h, --help            show this help message and exit
    -v VERSION, --version VERSION
                        Optional version string of the application to stop. If
                        the application was deployed with a version string, it
                        must be specified in order to stop the application.

Some commands, like deploy, config, and theme have multiple sub-commands.

tomcat-manager> deploy -h
usage: deploy [-h] deployment_method ...

deploy an application to the tomcat server

positional arguments:
    deployment_method
    local            transmit a war file from the local file system to the server
    server           deploy a war file from the server file system
    context          deploy a context file from the server file system

options:
    -h, --help         show this help message and exit

type 'deploy [deployment_method] -h' for more help

Each sub-command also has help:

tomcat-manager> deploy context -h
usage: deploy context [-h] [-v VERSION] contextfile [warfile] path

deploy a context file from the server file system

positional arguments:
    contextfile           the java-style path (use slashes not backslashes) to the war file on the
                        server file system; don't include 'file:' at the beginning
    warfile               the java-style path (use slashes not backslashes) to the war file on the
                        server file system; don't include 'file:' at the beginning; overrides
                        'docBase' specified in the 'contextfile'
    path                  context path, including the leading slash, on the server where the warfile
                        will be available; overrides the context path in 'contextfile'.

options:
    -h, --help            show this help message and exit
    -v, --version VERSION
                        version string to associate with this deployment

This document does not include detailed explanations of every command. It does show how to connect to a Tomcat server and deploy a war file, since there are quite a few options for both of those commands. For everything else, the built-in help should be sufficient.

Connect and Deploy

Connect To A Tomcat Server

Before you can do anything to a Tomcat server, you need to enter the connection information, including the url and the authentication credentials. You can pass the connection information on the command line:

$ tomcat-manager --user=ace http://localhost:8080/manager
Password: {you type your password here}

Or:

$ tomcat-manager --user=ace --password=newenglandclamchowder \
http://localhost:8080/manager

You can also enter this information into the interactive prompt:

$ tomcat-manager
tomcat-manager> connect http://localhost:8080/manager ace newenglandclamchowder

Or:

$ tomcat-manager
tomcat-manager> connect http://localhost:8080/manager ace
Password: {type your password here}

See Authentication for complete details on all supported authentication mechanisms.

Deploy applications

Tomcat applications are usually packaged as a WAR file, which is really just a zip file with a different extension. The deploy command sends a WAR file to the Tomcat server and tells it which URL to deploy that application at.

The WAR file can be located in one of two places: some path on the computer that is running Tomcat, or some path on the computer where the command line tomcat-manager program is running.

If the WAR file is located on the same server as Tomcat, we call that server. If the WAR file is located where tomcat-manager is running, we call that local. If the file is already on the server, then we have to tell Tomcat where to go find it. If it’s local, then we have to send the WAR file over the network so Tomcat can deploy it.

For all of these examples, lets assume I have a Tomcat server running far away in a data center somewhere, accessible at https://www.example.com. I’m running the command line tomcat-manager program on my laptop. We’ll also assume that we have already connected to the Tomcat server, using one of the methods just described in Connect To A Tomcat Server.

For our first example, let’s assume we have a WAR file already on our server, in /tmp/fancyapp.war. To deploy this WAR file to https://www.example.com/fancy:

tomcat-manager> deploy server /tmp/myfancyapp.war /fancy

Now let’s say I just compiled a WAR file on my laptop for an app called shiny. It’s saved at ~/src/shiny/dist/shinyv2.0.5.war. I’d like to deploy it to https://www.example.com/shiny:

tomcat-manager> deploy local ~/src/shiny/dist/shiny2.0.5.war /shiny

Sometimes when you deploy a WAR you want to specify additional configuration information. You can do so by using a context file. The context file must reside on the same server where Tomcat is running.

tomcat-manager> deploy context /tmp/context.xml /sample

This command will deploy the WAR file specified in the docBase attribute of the Context element so it’s available at https://www.example.com/sample.

Note

When deploying via context files, be aware of the following:

  • The path attribute of the Context element is ignored by the Tomcat Server when deploying from a context file.

  • If the Context element specifies a docBase attribute, it will be used even if you specify a war file on the command line.

Parallel Deployment

Tomcat supports a parallel deployment feature which allows multiple versions of the same WAR to be deployed simultaneously at the same URL. To utilize this feature, you need to deploy an application with a version string. The combination of path and version string uniquely identify the application.

Let’s revisit our shiny app. This time we will deploy with a version string:

tomcat-manager> deploy local ~/src/shiny/dist/shiny2.0.5.war /shiny -v v2.0.5
tomcat-manager> list
Path                     Status  Sessions Directory
------------------------ ------- -------- ------------------------------------
/                        running        0 ROOT
/manager                 running        0 manager
/shiny                   running        0 shiny##v2.0.5

Later today, I make a bug fix to ‘shiny’, and build version 2.0.6 of the app. Parallel deployment allows me to deploy two versions of that app at the same path, and Tomcat will migrate users to the new version over time as their sessions expire in version 2.0.5.

tomcat-manager> deploy local ~/src/shiny/dist/shiny2.0.6.war /shiny -v v2.0.6
tomcat-manager> list
Path                     Status  Sessions Directory
------------------------ ------- -------- ------------------------------------
/                        running        0 ROOT
/manager                 running        0 manager
/shiny                   running       12 shiny##v2.0.5
/shiny                   running        0 shiny##v2.0.6

Once all the sessions have been migrated to version 2.0.6, I can undeploy version 2.0.5:

tomcat-manager> undeploy /shiny --version v2.0.5
tomcat-manager> list
Path                     Status  Sessions Directory
------------------------ ------- -------- ------------------------------------
/                        running        0 ROOT
/manager                 running        0 manager
/shiny.                  running        9 shiny##v2.0.6

The following commands support the -v or --version option, which makes parallel deployment possible:

  • deploy

  • undeploy

  • start

  • stop

  • reload

  • sessions

  • expire

Settings

View All Settings

The settings command displays a list of settings which control the behavior of tomcat-manager:

tomcat-manager> settings
debug = false                        # show stack trace for exceptions
echo = false                         # for piped input, echo command to output
editor = "/opt/homebrew/bin/emacs"   # program used to edit files
prompt = "tm> "                      # displays before accepting user input
quiet = false                        # suppress all feedback and status output
status_prefix = "--"                 # string to prepend to all feedback output
status_animation = "bouncingBar"     # style of activity spinner from rich.spinner
status_suffix = "..."                # suffix to append to status messages
status_to_stdout = false             # status information to stdout instead of stderr
theme = "default-dark"               # color scheme
timeout = 10.0                       # seconds to wait for HTTP connections
timing = false                       # report execution time upon command completion
Change a Setting

You can change any of these settings using the set command:

tomcat-manager> set prompt = "tm> "
tm> set timeout = 3

You can also change settings using the Configuration File.

The syntax of the set command is simple. The first argument is the name of the setting. You can see all by typing settings, or by scrolling down.

The second argument is an equals sign, ie =.

The third argument is the value of the setting. For settings that are on or off, use either true or false. For settings that are a number, like timeout, just type the number. For settings that are a string, like prompt, enclose the value in quote marks.

Here’s a detailed description of each available setting.

debug

The default value is false. If set to true a Python stack trace will be displayed when an exception occurs.

echo

The default value is false. If you are piping input into tomcat-manager from the shell, it may be useful to have those commands injected into the output, so you can see the command and the output together. Set to true to echo piped input commands into the output.

This setting has no effect if the input is not piped from the operating system shell. If you turn this on, and are interactively typing commands into tomcat-manager, they will not be displayed in the output.

editor

The editor setting contains the full path to the program that tomcat-manager should invoke to edit text files. This setting is used by several commands, most notable is the config edit command used to edit the configuration file. If this setting does not have a value, the contents of the EDITOR environment variable will be used.

prompt

When used interactively, the tomcat-manager program displays a prompt before accepting user input. This setting contains the text to be displayed as the prompt. You can set this to be an empty string to disable the prompt, but that would be very confusing.

The default value is tomcat-manager>.

quiet

By default, tomcat-manager provides useful feedback and status information as it executes commands. If you don’t want to see this information, set quiet to true.

For example, when quiet is set to false (the default), the connect command displays:

tomcat-manager> connect http://localhost:8080/manager ace newenglandclamchowder
--connecting... [=== ]
--connected to http://localhost/manager as ace
--tomcat version: [Apache Tomcat/10.1.0]
tomcat-manager>

If you set quiet to true, no feedback information is displayed

tomcat-manager> set quiet = true
tomcat-manager> connect http://localhost:8080/manager ace newenglandclamchowder
tomcat-manager>
status_prefix

By default, all status and feedback messages begin with --. You can change or eliminate the prefix value by setting status_prefix. You might change it to:

tomcat-manager> set status_prefix = ">>"

Set status_prefix to an empty string to display the status messages with no prefix.

status_animation

Commands which run on the remote Tomcat server can take some time to finish. For example, if you are deploying a large application, it may take several seconds for that application to be transmitted to the server and deployed. tomcat-manager displays an animated activity indicator for these actions. This setting allows you to choose the style of the animation. There are several dozen options available. You can view all the animation styles by:

$ python -m rich.spinner

Press Control-C to exit the demo.

To disable the animated progress display:

tomcat-manager> set status_animation = ""
status_suffix

By default, all status and feedback messages end with ...`. You can change or eliminate the suffix by setting status_suffix to the value you would like appended to status and feedback messages.

Set status_suffix to an empty string to display status messages with no suffix.

status_to_stdout

By default, status and feedback messages are sent to the standard error file descriptor. Set status_to_stdout to true to send those messages to standard output.

theme

The theme to use to apply colors to output. See Themes for more information.

timeout

The number of seconds to wait for a HTTP response from the Tomcat server before timing out with an error. Set to 0 to never timeout (not recommended). Fractions of seconds are allowed, for example, you could:

tomcat-manager> set timeout = 3.5

The default value is 10.

timing

If timing is set to true, tomcat-manager will report the number of seconds it took for each command to execute after the command has completed. The number of seconds is displayed as feedback, which means if you have quiet set to true, you will not see it.

Configuration File

tomcat-manager reads a user configuration file on startup. This file allows you to:

  • change settings on startup

  • create Tomcat server definitions that include the url and authentication credentials

The `--noconfig command line option prevents tomcat-manager from processing the configuration file on startup.

Location

The location of the configuration file is different depending on your operating system. To see the location of the file on your system, run the following command from within tomcat-manager:

tomcat-manager> config file
/Users/kotfu/Library/Application Support/tomcat-manager/tomcat-manager.toml
Editing

You can edit the file from within tomcat-manager too. Well, it really just launches the editor of your choice, you know, the one specified in the editor setting . Do that by typing:

tomcat-manager> config edit
Syntax

The configuration file uses the TOML file format. TOML is a simple configuration file format that’s easy for humans to read. tomcat-manager doesn’t have complex configuration requirements, so TOML is a great fit. Here’s an example configuration file in TOML format:

[settings]
prompt = "tm> "
debug = true
editor = "/usr/bin/mg"
echo = false
quiet = false
status_prefix = "--"

[tcl]
url = "http://localhost:8080/manager"
user = "ace"
password = "newenglandclamchowder"

Note

In versions prior to 6.0.0, the configuration file used the Microsoft Windows INI file format, which is similar to TOML. For the tomcat-manager configuration file, the biggest difference between these two formats is that all string values must be quoted in TOML, and in INI they are accepted without quotes.

When you run tomcat-manager in interactive mode it will check if the old configuration file is present. If it is, and if the new configuration file doesn’t exist, it will let you know.

$ tomcat-manager
--In version 6.0.0 the configuration file format changed from INI to TOML.
--You have a configuration file in the old format. Type 'config convert' to
--migrate your old configuration to the new format.

Convert your configuration file to the new format:

tomcat-manager> config convert
--converting old configuration file to new format
--configuration written to /Users/kotfu/Library/Application Support/tomcat-manager/tomcat-manager.toml
--reloading configuration

Everything is converted to the new format automatically except comments. You’ll have to add your comments back in by hand.

Settings

Create a table called settings, and use key/value pairs to set values for any of the available settings. These settings are applied when tomcat-manager starts, and applied again after you finish editing the config file. Here’s an example of settings in the config file:

[settings]
prompt = "tm> "
debug = true
editor = "/usr/bin/mg"
echo = false
quiet = false
status_prefix = "--"

See Settings for documentation on every setting.

Server Definitions

In addition to settings, you can use the configuration file to define Tomcat servers. The definition includes a name, the url, and authentication credentials. Create server definitions in your configuration file to keep the the authentication credentials off of the command line and out of your scripts, which is more secure.

A server definition is contained in a TOML table. The name of the table is the name of the server, and the various items in the table contain the details about that server. Here’s a simple example:

[local]
url = "http://localhost:8080/manager"
user = "ace"
password = "newenglandclamchowder"

With this defined in your configuration file, you can now connect using the name of the server:

tomcat-manager> connect local

You can also use the server name from the command line instead of providing the url:

$ tomcat-manager local

If you define a user, but omit password, you will be prompted for it when you use the server definition in the connect command.

Here’s all the properties supported in a server definition:

url

Url of the server.

user

User to use for HTTP Basic authentication.

password

Password to use for HTTP Basic authentication. If user is provided and password is not, you will be prompted for a password.

cert

File containing certificate and key, or just a certificate, for SSL/TLS client authentication. See SSL/TLS Client Authentication for more information.

key

File containing private key for SSL/TLS client authentication. See SSL/TLS Client Authentication for more information.

cacert

File or directory containing a certificate authority bundle used to validate the SSL/TLS certificate presented by the server if the url uses the https protocol. See Encrypted Connections for more information.

verify

Defaults to True to verify server SSL/TLS certificates. If False, no verification is performed.

When using a server definition, you can override properties from the definition on the command line. For example, if we had a server defined like this:

[prod]
url = "https://www.example.com/manager"
user = "ace"
password = "newenglandclamchowder"
cacert = "/etc/mycacert"

You could use that server definition but temporarily disable verification of server SSL/TLS certificates:

tomcat-manager> connect prod --noverify

Or you could override the user and password:

tomcat-manager> connect prod root Z1ON0101

Some of these properties make no sense when combined together. For example, if your server authenticates with a certificate and key, it almost certainly doesn’t use a user and password. If you don’t want to verify server SSL/TLS certificates, then it makes no sense to provide a certificate authority bundle. See Authentication for complete details of all supported authentication mechanisms.

Themes

When a theme is set, tomcat-manager displays colored output using the styles defined in theme. By default, no theme is applied; all output is displayed using the default style of your terminal emulator. See https://no-color.org for an explanation of why this is the best approach.

tomcat-manager comes with several built-in themes which use can use. Built-in themes can not be edited or modified. You can create your own themes, either from scratch or by cloning a built-in theme. If connected to the internet, you can view a gallery of themes available online, and install any of them computer. Once installed, they can be applied and modified to your liking.

A theme is defined in a file using the TOML format. The file contains a set of scope definitions, and the style to use when rendering each scope. Here’s a simple example showing several scopes and their associated styles:

[tm]
error =  "#d70000"
status =  "#00afff"

[tm.help]
category =  "gold1"
border = "gold1"

For convenience, we use the table features of TOML. Those same four scopes could also be defined as:

tm.error = "#d70000"
tm.status =  "#00afff"
tm.help.category =  "gold1"
tm.help.border = "gold1"

All scopes and a description of how they are used are listed in Theme Scopes. A style specifies colors and attributes (like bold or italic) to use when rendering the scope. See Styles for more information

Listing Themes

The following command displays all themes known to tomcat-manager:

tomcat-manager> theme list
Gallery Themes
────────────────────────────────────────────────────────────────────────
monokai           monokai theme using color scheme from https://monokai.pro/
solarized-dark    dark theme using solarized color scheme from
                    https://ethanschoonover.com/solarized/
solarized-light   light theme using solarized color scheme from
                    https://ethanschoonover.com/solarized/

User Themes
────────────────────────────────────────────────────────────────────────
default-light*   tomcat-manager default theme for use on light backgrounds
default-dark*    tomcat-manager default theme for use on dark backgrounds

'*' indicates a read-only built-in theme.
Make your own copy of a built-in or gallery theme with 'theme clone'.
You can then edit your copy of the theme with 'theme edit'.

The themes are divided into two sections. Gallery themes are retrieved from a website and must be installed locally before they can be used. User themes have already been installed and are available for use. Some themes are included with the tomcat-manager distribution, and are marked with an asterisk to indicate they are built-in. These themes can be used and cloned, but may not be modified. You can clone one of these built-in themes and give it the same name, if you do so, the asterisk will disappear and you will be able to edit the theme.

Setting a Theme

When tomcat-manager is launched, it checks the following items in the order given until it finds a theme setting. If no theme is set by any of these items, then no theme is applied.

  • --theme command line option

  • TOMCATMANAGER_THEME environment variable

  • the theme setting in the configuration file

If you have a setting in your config file to set the theme:

[settings]
theme = "default-light"

And you invoke tomcat-manager using the following:

$ tomcat-manager --theme default-dark

The theme will be set to default-dark, because the command line option is checked first, and if found, all other mechanisms to set the theme are ignored.

This approach has been implemented because it offers great flexibility and makes integration with other shell tools and environments easy.

Once tomcat-manager is running, you can apply a new theme by by changing the theme setting to the name of the theme you want to load. Any future output will now be generated using the styles specified in the loaded theme.

tomcat-manager> set theme = "default-dark"

If you don’t want to use a theme, type:

tomcat-manager> set theme = ""

tomcat-manager comes with built-in themes which can not be changed. If you create your own theme with the same name as one of the built-in themes your theme will be loaded instead of the built-in theme with the same name.

Creating a User Theme

There are four ways to create a user theme:

  • clone a gallery theme

  • clone a built-in theme

  • create a new theme from scratch

  • copy a theme file from another computer

Once you have a user theme, you can freely edit it.

Use the following command to clone a gallery or built-in theme to a user theme:

tomcat-manager> theme clone solarized-dark

You can use theme list to verify that the theme has been successfully cloned.

To create a new user theme from scratch, use:

tomcat-manager> theme create my-new-theme

A new theme file will be created from a template which includes all available scopes. You can then edit the theme, adding Styles to the scopes to achieve the desired color output.

Any user theme file can be copied to another computer. Place it in the local theme directory to make it avaialble to tomcat-manager.

Location of Theme Files

User themes are stored in a configuration directory. The location of this directory is different depending on the operating system. You can see the exact directory for your setup by typing the following from your operating system shell prompt:

$ tomcat-manager --theme-dir
/Users/kotfu/Library/Application Support/tomcat-manager/themes

You can get the same information from within tomcat-manager by typing:

tomcat-manager> theme dir
/Users/kotfu/Library/Application Support/tomcat-manager/themes

When you clone a theme from the gallery, or create a new theme, it is placed into this directory. Any actions you take on files in this directory (deleting, renaming, copying, etc) are immediately recognized in the tomcat-manager tool.

Theme files from this directory can be shared or copied to another computer.

Editing a Theme

Gallery themes are not available to edit. They can be cloned to your local machine, and then freely edited. Built-in themes are local, but they are read-only. See Listing Themes above to learn how to display all available themes.

Edit a user theme by:

tomcat-manager> theme edit [name]

replacing [name] with the name of the user theme. The theme file will open in your editor of choice (see editor setting). If you edit the currently loaded theme, it will be reloaded after the editor exits.

See Theme Scopes and Styles for documentation on what to put in a theme file to create the desired output.

Deleting a Theme

You can delete any user theme (except for the read-only build-in themes):

tomcat-manager> theme delete [name]

replacing [name] with the name of the user theme you would like to delete. You will be prompted to confirm the deletion unless you provide the -f option.

Theme Scopes

Here’s a list of all the scopes which tomcat-manager can use when defined in a theme. In this example, all scopes are set to a style of default, which displays the scope in the default foreground and background color of your terminal emulator.

If a theme contains unknown scopes, they will be ignored.

# These scopes are applied to output generated by many commands.
[tm]
# error messages
error =  "default"
# status messages
status =  "default"
# progress animations for long-running commands (like connect or list)
animation = "default"


# When run with no arguments, the 'help' command shows a categorized list
# of all the available commands. These scopes control the display of that
# categorized list.
[tm.help]
# the name of a category or grouping of commands
category =  "default"
# the border line below the category  name
border = "default"
# the name of the command shown in the first column
command =  "default"
# arguments to the 'help' command
args = "default"


# These scopes are used when displaying help or usage for a specific command
# i.e. when typing 'connect -h' or 'help connect'.
[tm.usage]
# name of the command
prog =  "default"
# groups of arguments, ie 'positional arguments:', and 'options:'
groups =  "default"
# the positional arguments and options
args =  "default"
# values for options, ie KEY is the metavar in '--key KEY'
metavar =  "default"
# the description of positional arguments and options
help =  "default"
# command descriptions, epilogs, and other text
text =  "default"
# syntax or references inline in other text
syntax =  "default"


# Used by the 'list' command which shows information about each
# application deployed in the Tomcat server.
[tm.list]
# column headers in the table of displaye dinformation
header =  "default"
# the border line underneath the column headers
border =  "default"


# When showing details of an app deployed in a tomcat server,
# like by the list command, use these scopes for attributes
# of each application.
[tm.app]
# if the application is running, show the word 'running' in this style
running =  "default"
# if the application is stopped, show the word 'stopped' in this style
stopped =  "default"
# show the number of active sessions in this style
sessions =  "default"

# These scopes are used by the 'settings' command to show the various
# program settings.
[tm.setting]
# name of the setting
name =  "default"
# the equals sign separating the setting from it's value
equals =  "default"
# the comment containing the description of the setting
comment =  "default"
# values which are strings, like 'prompt'
string =  "default"
# values which are boolean, like 'debug' and 'echo
bool =  "default"
# values which are integers, we have no settings with integer values
# but have added it to all themes just in case
int =  "default"
# values which are floats, like 'timeout'
float =  "default"


# These scopes used by the 'theme list' command to show all available themes
[tm.theme]
# the category or group name of a set of themes
category = "default"
# the border line below the category name
border = "default"
Styles

You can set a style for each theme scope. If you set the style to default or if the scope is not present in the theme file, no codes will be sent to your terminal emulator to style that scope. That means that text in that scope will be displayed in the default colors of your terminal emulator.

A style can specify colors and attributes (like bold or italic). Ancient terminals are monochrome, really old terminals could display 16 colors, old terminals can display 256 colors, most modern terminals can display 16.7 million colors.

Specify a color using any of the following:

Color Specification

Description

#8700af

CSS-style hex notation

rgb(135,0,175)

RGB form using three integers

dark_magenta

color names

color(91)

color numbers

Color names and numbers are shown at https://rich.readthedocs.io/en/stable/appendix/colors.html

All of the above forms produce the exact same color.

When only one color is specified in the style, it will set the foreground color. To set the background color, preceed the color with the word “on”.

  • white on rgb(135,0,75)

  • #ffffff on dark_magenta

As shown above, you can mix and match the color specification format in a single style. For consistency, I recommend that you pick one color specification format and use it. The built-in themes use color names for two reasons:

  • The color names limit you to the 256 color space, making the theme work on a larger variety of terminal emulators

  • For those of us who can’t intuitively translate hex into colors, the names give you some idea of what the color is.

Specify additional text attributes by adding additional words to the style:

  • #ffffff on #8700af bold strike

  • color(91) underline

The most useful text attributes are:

Attribute

Description

bold

bold or heavy text

italic

italic text (not supported on Windows)

strike

text with a strikethrough line

underline

underlined text

For more examples and additional documentation on styles, see https://rich.readthedocs.io/en/stable/style.html

Additional Features

Readline Editing

You can edit current or previous commands using standard readline editing keys. If you aren’t familiar with readline, just know that you can use your arrow keys, home to move to the beginning of the line, end to move to the end of the line, and delete to forward delete characters.

Command History

Interactive mode keeps a command history, which you can navigate using the up and down arrow keys. and search the history of your commands with <control>+r.

You can view the list of previously issued commands:

tomcat-manager> history

And run a previous command by string search:

tomcat-manager> history -r undeploy

Or by number:

tomcat-manager> history -r 10

The history command has many other options, including the ability to save commands to a file and load commands from a file. Use help history to get the details.

Shell-style Output Redirection

Save the output of the list command to a file:

tomcat-manager> list > /tmp/tomcat-apps.txt

Search the output of the vminfo command:

tomcat-manager> vminfo | grep user.timezone
  user.timezone: US/Mountain

Or the particularly useful:

tomcat-manager> threaddump | less
Clipboard Integration

You can copy output to the clipboard by redirecting but not giving a filename:

tomcat-manager> list >

You can also append output to the clipboard using a similar method:

tomcat-manager> serverinfo >>
Run shell commands

Use the shell or ! commands to execute operating system commands (how meta):

tomcat-manager> !ls

Of course tab completion works on shell commands.

Python Interpreter

You can launch a python interpreter:

tomcat-manager> py
Python 3.10.0 (default, Oct  7 2021, 15:03:23) [Clang 11.0.3 (clang-1103.0.32.62)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

Use `Ctrl-D` (Unix) / `Ctrl-Z` (Windows), `quit()`, `exit()` to exit.
Run CLI commands with: app("command ...")

>>> self.tomcat
<tomcatmanager.tomcat_manager.TomcatManager object at 0x10f652a40>
>>> self.tomcat.is_connected
True
>>> exit()
Now exiting Python shell...

As you can see, if you have connected to a Tomcat server, then you will have a self.tomcat object available which is an instance of TomcatManager. See Use from Python for more information about what you can do with this object.

Command Line

You’ve already read about interactive use right? If not, this part will feel kind of hollow.

Any interactive command can be run from the command line. The first positional argument to tomcat-manager is the url of the server. The rest of the arguments are any commands and their arguments from Available Commands. Here’s a few examples:

$ tomcat-manager --user ace --password newenglandclamchowder \
http://localhost:8080/manager deploy server /tmp/myfancyapp.war /fancy
$ tomcat-manager --user ace --password newenglandclamchowder \
http://localhost:8080/manager list --state running --by path

Using Shell Scripts

Say you want to find out how many active sessions there are in the oldest version of our shiny app (told you it would feel kind of hollow). You could use interactive mode:

$ tomcat-manager
tomcat-manager>connect https://www.example.com/manager ace newenglandclamchowder
--connected to https://www.example.com/manager as ace
tomcat-manager>list
Path                     Status  Sessions Directory
------------------------ ------- -------- ------------------------------------
/                        running        0 ROOT
/manager                 running        0 manager
/shiny                   running       17 shiny##v2.0.6
/shiny                   running        6 shiny##v2.0.5

If you need to automate a more complex sequence of commands or parse the output, you might choose to use tomcat-manager from within a shell script:

#!/usr/bin/env bash
#
URL=https://www.example.com/manager
USERID=ace
PASSWD=newenglandclamchowder
COMMAND="list --raw"
TOMCAT="tomcat-manager --quiet --user=$USERID --password=$PASSWD $URL $COMMAND"

# get the output of the list into a shell variable
LIST=$($TOMCAT)

# if the tomcat command completed successfully
TOMCAT_EXIT=$?
if [ "$TOMCAT_EXIT" -eq 0 ]; then
    echo "$LIST" | grep '^/shiny' | awk -F ':' '{ print $4":"$3}' | \
    sort | head -1 | awk -F ':' '{ print #2 }'
else
    # list has an error message, not the list of tomcat apps
    echo -n "$LIST"
    exit $TOMCAT_EXIT
fi

Save this script as ~/bin/oldshiners.sh, and then run it:

$ ~/bin/oldshiners.sh
6

This script builds a tomcat-manager command which includes authentication credentials, the url where the Tomcat Manager web app is deployed, as well as the command from Available Commands. In this example, we used list as our command. Any command that works in the interactive mode works on the command line.

Note how we check the exit code in the shell. tomcat-manager knows whether the command to the tomcat server completed successfully or not, and sets the shell exit code appropriately. The exit codes are:

0 = command completed succesfully
1 = command had an error
2 = incorrect usage
127 = unknown command

Timeout

By default, network operations timeout in 10 seconds. You can change this value in the configuration file. You can also override it on the command line.

$ tomcat-manager --timeout=2.5 http://localhost:8080/manager list

This command line option allows you to override the timeout setting.

Authentication

Use the user you created when you Configured Tomcat on the command line:

$ tomcat-manager --user=ace http://localhost:8080/manager list
Password:

and you will be prompted for the password. You can also specify the password on the command line, but this is not secure:

$ tomcat-manager --user=ace --password=newenglandclamchowder \
http://localhost:8080/manager list
Password:

See Authentication for complete details of all supported authentication mechanisms.

If you want unattended authenticated access, server definitions are a better option.

Server Definitions

You can use Server Definitions from the command line with or without commands:

$ tomcat-manager localhost
--connected to http://localhost:8080/manager as ace
tomcat-manager>list
Path                     Status  Sessions Directory
------------------------ ------- -------- ------------------------------------
/                        running        0 ROOT
/manager                 running        0 manager

Or:

$ tomcat-manager localhost list
--connected to http://localhost:8080/manager as ace
Path                     Status  Sessions Directory
------------------------ ------- -------- ------------------------------------
/                        running        0 ROOT
/manager                 running        0 manager

This mechanism allows you to keep all authentication credentials out of your scripts. Simply create server definitions with credentials for the server(s) you want to manage, and reference the definitions in your scripts. Instead of this:

TOMCAT="tomcat-manager --user=$USERID --password=$PASSWD $URL $COMMAND"

you might use this:

TOMCAT="tomcat-manager example $COMMAND"

with the following in your configuration file:

[example]
url = "https://www.example.com"
user = "ace"
password = "newenglandclamchowder"

Piped Input

tomcat-manager will process lines from standard input as though they were entered at the interactive prompt. There is no mechanism to check for errors this way, the commands are blindly run until the pipe is closed. The shell exit code of tomcat-manager will be the exit code of the last command run.

If you want to see what the exit codes are, you can either use $? in your shell, or you can use the interactive command exit_code ($? works too) to see the result.

If you want more sophisticated error checking, then you should probably write a shell script and invoke tomcat-manager seperately for each command you want to execute. That will allow you to use the shell script for checking exit codes, logic branching, looping, etc.

Controlling Output

When using tomcat-manager from the command line, you have fine grained control of what you want included in the output. As a well-behaved shell program it sends output to stdout and errors to stderr. If you are using bash or one of the other sh variants, you can easily co-mingle them into a single stream:

$ tomcat-manager localhost list > myapps.txt 2>&1

In addition to redirecting with the shell, there are several command line switches that change what’s included in the output. These options correspond to Setting you can change in interactive use. All of the settings default to False, but be aware that you may have altered them your configuration file, which is read on startup.

Option

Setting

Description

-e, --echo

echo

Add the command to the output stream.

-q, --quiet

quiet

Don’t show non-essential feedback.

-s, --status-to-stdout

status_to_stdout

Send status information to stdout instead of stderr.

-d, --debug

debug

Show detailed exception and stack trace, even if quiet is True.

Some commands show additional status information during their execution which is not part of the output. If quiet=True then all status output is suppressed. If quiet=False then status information is sent to stderr. If status_to_stdout=True then status information is sent to stdout, as long as quiet=False.

Here’s a couple of examples to demonstrate, using a server definition of localhost, which we assume gets you authenticated to a Tomcat Server web application:

These two commands yield the same output, but by different mechanisms: the first one uses the shell to redirect status messages to the bitbucket, the second one uses the --quiet switch to instruct tomcat-manager to suppress status messages.

$ tomcat-manager localhost list 2>/dev/null
Path                     Status  Sessions Directory
------------------------ ------- -------- ------------------------------------
/                        running        0 ROOT
/manager                 running        0 manager
$ tomcat-manager --quiet localhost list 2>/dev/null
Path                     Status  Sessions Directory
------------------------ ------- -------- ------------------------------------
/                        running        0 ROOT
/manager                 running        0 manager

If you pipe commands into tomcat-manager instead of providing them as arguments, the --echo command line switch can be included which will print the prompt and command to the output:

$ echo list | tomcat-manager --echo localhost
--connected to https://home.kotfu.net/manager as ace
tomcat-manager> list
Path                     Status  Sessions Directory
------------------------ ------- -------- ------------------------------------
/                        running        0 ROOT
/manager                 running        0 manager

For most common errors, like failed authorization, connection timeouts, and DNS lookup failures, tomcat-manager catches the exceptions raised by those errors, and outputs a terse message describing the problem. For example, if my Tomcat container is not currently running, or if the HTTP request fails for any other reason, you will see something like this:

$ tomcat-manager vm list
connection error

If you want all the gory detail, give the --debug command line switch or set debug=True. Then you’ll see something like this (stack trace truncated with ‘…’):

$ tm --debug vm list
Traceback (most recent call last):
    File "/Users/kotfu/.pyenv/versions/3.6.2/envs/tomcatmanager-3.6/lib/python3.6/site-packages/urllib3/connection.py", line 141, in _new_conn
    (self.host, self.port), self.timeout, **extra_kw)
    File "/Users/kotfu/.pyenv/versions/3.6.2/envs/tomcatmanager-3.6/lib/python3.6/site-packages/urllib3/util/connection.py", line 83, in create_connection
    raise err
    File "/Users/kotfu/.pyenv/versions/3.6.2/envs/tomcatmanager-3.6/lib/python3.6/site-packages/urllib3/util/connection.py", line 73, in create_connection
    sock.connect(sa)
socket.timeout: timed out
...
requests.exceptions.ConnectTimeout: HTTPConnectionPool(host='192.168.13.66', port=8080): Max retries exceeded with url: /manager/text/serverinfo (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x103180a20>, 'Connection to 192.168.13.66 timed out. (connect timeout=2)'))

Use from Python

Connect to the server

Before you can do anything useful, you need to create a TomcatManager object and connect to a server.

TomcatManager.connect(url: str, user: str = '', password: str = '', *, cert: str | Tuple[str, str] = None, verify: str | bool = True, timeout: float = None) TomcatManagerResponse

Connect to the manager application running in a Tomcat server.

Parameters:
  • url – url where the Tomcat Manager web application is deployed

  • user – (optional) user to authenticate with

  • password – (optional) password to authenticate with

  • cert – client side certificates to use for SSL/TLS authentication

  • verify – verify server SSL/TLS certificates

  • timeout – timeout in seconds for network operations

Returns:

TomcatManagerResponse object with an additional server_info attribute

The server_info attribute of the returned object contains a ServerInfo object, which is a dictionary with some added properties for well-known values returned from the Tomcat server.

This method:

  • sets or changes the url, credentials, and certificates on an existing object

  • provides a convenient mechanism to validate you can actually connect to the server

  • returns a response object that includes information about the server you are connected to

  • allows you to inspect the response so you can see why you can’t connect

Usage

>>> import tomcatmanager as tm
>>> url = "http://localhost:808099/manager"
>>> user = "ace"
>>> password = "newenglandclamchowder"
>>> tomcat = tm.TomcatManager()
>>> try:
...     r = tomcat.connect(url, user, password)
...     if r.ok:
...         print("connected")
...     else:
...         print("not connected")
... except Exception as err:
...    # handle exception
...    print("not connected")
not connected

Many things can go wrong when requesting url’s via http. tomcatmanager uses the requests library for all network communication, and follows that library’s approach for raising exceptions and checking the response to your request. Therefore:

  • Some exceptions will always be raised by this method. If you give a URL where no web server is listening, requests.connections.ConnectionError will be raised.

  • Other exceptions will only be raised if you call TomcatManagerResponse.raise_for_status(). For example, if the credentials are incorrect, you won’t get an exception unless you ask for it.

  • The TomcatManagerResponse.ok attribute is the easiest and most rigerous way to check whether you connected successfully. However, as the example usage above shows, you still have to catch exceptions because requests can raise exceptions from inside the connect() method and this library doesn’t attempt to catch them so that you can do specific error handling if you want to.

All communications between this library and a Tomcat server happen over HTTP, which means there isn’t a persistent connection. A new HTTP GET request is issued for each method call on this object (i.e. deploy_localwar(), stop()). However, the mental model for this library is connection based: use the connect() method to establish the URL and authentication credentials, then call other methods to perform actions on the server you are connected to. If you try and call other methods before you call connect(), TomcatNotConnected will be raised. Because there is no persistent connection of any kind, there is no disconnect method and no cleanup to perform when you are done using a server.

If you discard or don’t save the return object from this method, you can call is_connected() to check if you are connected.

Authentication

The only way to validate the URL and authentication credentials is to make an HTTP request to the server and see if it returns successfully. Internally this method tries to retrieve /manager/text/serverinfo.

Typically authentication is done via user and password. Pass those parameters to utilize HTTP Basic authentication.

To authenticate with a SSL/TLS server using a client certificate and key, pass the path to a single file containing the private key and certificate in the cert parameter. As an alternative, you can pass a tuple containing the path to the certificate, and the path to the key.

Warning

The private key for your local certificate must be unencrypted. The Requests library used for network communication does not support using encrypted keys.

If the URL uses the https protocol, the default behavior is to validate the server SSL/TLS certificate chain.

To validate with your own certificate authority bundle, set the verify parameter to the path to a certificate authority bundle file or a directory of certificates of trusted certificate authorities. You can disable server certificate validation by setting verify to False.

See Authentication for more details.

Side Effects

Passing a timeout parameter to this method has the side effect of setting the timeout attribute on this object.

Requesting url’s via http can also result in redirection to another url. If that occurs, the new url, not the one you passed, will be stored in the url attribute.

If you pass user and password credentials and the connection is successful, the user will be stored in the user attribute.

If you pass an authentication key and certificate in the cert parameter and the connection is successful, the information will be stored in the cert attribute.

Upon successful connection, an instance of TomcatMajorMinor will be stored in tomcat_major_minor indicating the major version of Tomcat running on the server. Further details about the server are available in the server_info attribute of the returned response.

Changed in version 3.0.0:

Responses from the server

All the methods of TomcatManager which interact with the server return a response in the form of a TomcatManagerResponse object. Use this object to check whether the command completed successfully, and to get any results generated by the command.

class tomcatmanager.models.TomcatManagerResponse(response: Response = None)

Returned as the response for TomcatManager commands.

After running a command, it’s a good idea to check and make sure that the command completed succesfully before relying on the results:

>>> import tomcatmanager as tm
>>> tomcat = getfixture("tomcat")
>>> try:
...     r = tomcat.server_info()
...     r.raise_for_status()
...     if r.ok:
...         print(f"Operating System: {r.server_info.os_name}")
...     else:
...         print(f"Error: {r.status_message}")
... except Exception as err:
...     # handle exception
...     pass
Operating System: ...
status_code

Status of the Tomcat Manager command from the first line of text.

The preferred way to check for success is to use the ok() method, because it checks for http errors as well as tomcat errors. However, if you want specific access to the status of the tomcat command, use this method.

The status codes are enumerated in StatusCode.

>>> import tomcatmanager as tm
>>> tomcat = getfixture("tomcat")
>>> r = tomcat.server_info()
>>> r.status_code == tm.StatusCode.OK
True
status_message

The message on the first line of the response from the Tomcat Server.

result

The text of the response from the Tomcat server, without the first line (which contains the status code and message).

property ok
Returns:

True if the request completed with no errors.

For this property to return True:

  • The HTTP request must return a status code of 200 OK

  • The first line of the response from the Tomcat Manager web application must begin with OK.

raise_for_status()

Raise exceptions for server errors.

First this method calls requests.Response.raise_for_status() which raises exceptions if a 4xx or 5xx response is received from the server.

If that doesn’t raise anything, then it raises a TomcatError if there is not an OK response from the first line of text back from the Tomcat Manager web app.

property response: Response

The server’s response to an HTTP request.

TomcatManager uses the excellent Requests package for HTTP communication. This property returns the requests.Response object which contains the server’s response to the HTTP request.

Of particular use is requests.Response.text which contains the content of the response in unicode. If you want raw access to the content returned by the Tomcat Server, this is where you can get it.

Managing Applications

This library provides a robust API to manage applications in a tomcat server. The following methods are available:

Parallel Deployment

Tomcat supports a parallel deployment feature which allows multiple versions of the same WAR to be deployed simultaneously at the same URL. To utilize this feature, you need to deploy an application with a version string. The combination of path and version string uniquely identify the application:

>>> tomcat = getfixture("tomcat")
>>> safe_path = getfixture("safe_path")
>>> localwar_file = getfixture("localwar_file")
>>> with open(localwar_file, "rb") as localwar_fileobj:
...     r = tomcat.deploy_localwar(safe_path, localwar_fileobj, version="42")
...     r.ok
True
>>> with open(localwar_file, "rb") as localwar_fileobj:
...     r = tomcat.deploy_localwar(safe_path, localwar_fileobj, version="43")
...     r.ok
True

We now have two instances of the same application, deployed at the same location, but with different version strings. To do anything to either of those applications, you must supply both the path and the version string:

>>> r = tomcat.stop(path=safe_path, version="42")
>>> r.ok
True
>>> r = tomcat.undeploy(path=safe_path, version="42")
>>> r.ok
True
>>> r = tomcat.undeploy(path=safe_path, version="43")
>>> r.ok
True

The following methods include an optional version parameter to support parallel deployments:

Information about Tomcat

There are a number of methods which just return information about the Tomcat server. With the exception of TomcatManager.find_leakers() (which triggers garbage collection), these methods don’t effect any change on the server.

SSL/TLS

Tomcat servers can be configured to serve their applications over SSL/TLS. This library includes a few related methods:

The TomcatManager.ssl_reload() is the only one of these methods that causes the server to take any action, the rest are informational only.

Differences in Tomcat Versions

As Tomcat matured, it added new capabilities. For example, Tomcat 8.5 added a new command ssl_reload. This library added support for that command in version 2.0.0. However, if the server you were connected to happened to be running Tomcat 8.0, a somewhat rather generic exception was thrown.

In version 3.0.0, this library was enhanced so it understood all the supported versions of Tomcat (see TomcatMajorMinor), and which versions of Tomcat supported each of the available API calls.

If you call a method that is not implemented by the particular server you are connected to, TomcatNotImplementedError will be raised.

Note

In version 6.0.0 of this library and higher, all python API methods are available in all supported Tomcat versions. Therefore, this version of the library will not raise TomcatNotImplementedError exceptions.

However, you should still check for these exceptions in your code, and if you are already checking for them, you definitely shouldn’t delete those checks. This exception, and the related TomcatManager.implements() and TomcatManager.implemented_by() methods are not deprecated in case they are needed in future versions.

If you prefer to check whether a method is supported before calling it, you can do so using TomcatManager.implements():

>>> tomcat = getfixture("tomcat")
>>> if tomcat.implements(tomcat.list):
...     print("list is implemented")
... else:
...     print("list is not implemented")
list is implemented

If you call TomcatManager.implements() and are not connected to a server, TomcatNotConnected will be raised.

There is a way to check whether a method is supported without connecting to a server. You must specify the version of the Tomcat server and the method you want to check is implemented. Use one of the values in the enumeration TomcatMajorMinor to specify the version of Tomcat you want to check:

>>> import tomcatmanager as tm
>>> tomcat = tm.TomcatManager()
>>> tver = tm.TomcatMajorMinor.V8_5
>>> print(tomcat.implemented_by(tomcat.ssl_reload, tver))
True

Specifying As A Dependency

If you incorporate tomcatmanager into your own package, you will need to specify it as a dependency. I strongly recommend you specify the dependency such that it limits usage to a single major version of this library. This way when a new major version of this library is released, it won’t break your code. You should specify your pyproject.toml dependency like this:

[project]
dependencies = [
    "tomcatmanager>=5,<6"
]

When this library adds support for a new version of Tomcat or Python, we increment the minor version number. However, if support for these new versions requires API changes incompatible with prior releases of this software, then we increment the major version number.

When this library drops support for a version of Tomcat or Python, we increment the major version number. For example, when this project dropped support for Python 3.6, we released that version as 5.0.0 instead of 4.1.0, even though there were no incompatible API changes.

These versioning rules were chosen so that if you are using this library against a single version of Tomcat, and you specify your dependency rules as suggested above, you will not have to worry about a future release of this software breaking your setup.

For example, say you are using Tomcat 8.0, which is supported by version 5.x of this library. You should specify your pyproject.toml dependency rules:

[project]
dependencies = [
    "tomcatmanager>=5,<6"
]

When version 6.x of this library was released it dropped support for Tomcat 8.0. Without this dependency rule, pip would upgrade to the new version of this library, which would break your application which needs to talk to a Tomcat 8.0 server.

Once you have migrated your server infrastructure to a newer version of Tomcat, you can change your dependency rules:

[project]
dependencies = [
    "tomcatmanager>=6,<7"
]

Authentication

There are several methods available to ensure secure communication and authentication between tomcatmanager and a Tomcat server.

Encrypted Connections

For anything other than local development use, you should ensure that all communications with your Tomcat server are secured with SSL/TLS. Tomcat has extensive SSL/TLS configuration documentation. You can also configure a proxy to terminate SSL/TLS and pass the unencrypted traffic to Tomcat.

To use these encrypted connections with tomcatmanager, simply use the https protocol in the url you specify for the server. The list command shown here can be replaced with any supported command. Here are examples from the command line,

$ tomcat-manager --user=ace --password=newenglandclamchowder \
https://www.example.com/manager list

interactive mode,

$ tomcat-manager
tomcat-manager>connect https://www.example.com/manager ace newenglandclamchowder
--connected to https://www.example.com/manager as ace

and from Python:

url = 'https://www.example.com/manager'
user = 'ace'
password = 'newenglandclamchowder'
tomcat = tm.TomcatManager()
r = tomcat.connect(url, user, password)

Tomcatmanager uses the requests library for network communication. A SSL/TLS certificate presented by the server will be rejected if not signed by one of the certificate authorities included in requests.

Installing the certifi python package will cause requests to use Mozilla’s carefully curated collection of root certificates instead of the built-in ones. Highly recommended.

Server certificates from most commercial certificate authorities will just work. So will the free certificates issued by Lets Encrypt.

Using your own certificate authority

You can use your own certificate authority with a root certificate not cross-signed by one of the well known certificate authorities. You’ll need the path to your certificate authority bundle file, or the path to a directory containing certificates of trusted certificate authorities.

Note

If you use a directory, you must process the files in that directory using the c_rehash tool supplied with OpenSSL.

Use the --cacert option from the command line. The list command shown here can be replaced with any supported command.

$ tomcat-manager --user=ace --password=newenglandclamchowder \
--cacert=/etc/ssl/mycertbundle https://www.example.com/manager list

Interactive mode is similar:

$ tomcat-manager
tomcat-manager>connect --cacert=/etc/ssl/mycertbundle https://www.example.com/manager ace newenglandclamchowder
--connected to https://www.example.com/manager as ace

From Python use the verify parameter to the TomcatManager.connect() method:

url = "https://www.example.com/manager"
user = "ace"
password = "newenglandclamchowder"
cacert = "/etc/ssl/mycertbundle"
tomcat = tm.TomcatManager()
r = tomcat.connect(url, user, password, verify=cacert)
Disabling certificate verification

You can disable client verification of server SSL/TLS certificates. While useful in some development or testing scenarios, you should not do this when connecting to a production server.

Warning

With client verification disabled, a malicious actor can intercept communications from the client to the server without the user knowing.

Use the --noverify option from the command line:

$ tomcat-manager --user=ace --password=newenglandclamchowder \
--noverify https://www.example.com/manager list

from interactive mode:

$ tomcat-manager
tomcat-manager>connect --noverify https://www.example.com/manager ace newenglandclamchowder
--connected to https://www.example.com/manager as ace

or pass False in the verify parameter of the TomcatManager.connect() method:

url = "https://www.example.com/manager"
user = "ace"
password = "newenglandclamchowder"
tomcat = tm.TomcatManager()
r = tomcat.connect(url, user, password, verify=False)

HTTP Basic Authentication

All the examples in the tomcatmanager documentation demonstrate using a username and password to authenticate with the Tomcat server. This uses HTTP Basic Authentication which presents those credentials in the Authorization header of every HTTP request sent to the server.

This method is supported out of the box in the default configuration of Tomcat servers. When you add users and passwords to tomcat-users.xml you can authenticate as shown in any example in this documentation.

Warning

HTTP Basic Authentication is not secure when used over an unencrypted connection.

SSL/TLS Client Authentication

We’ve discussed how clients can verify servers using SSL/TLS, but what if a server want’s to verify a client? Servers configured with SSL/TLS Client Authentication use public key authentication to validate a certificate installed on the client.

As best I can tell, current versions of Tomcat do not support client authentication. I also can’t seem to find a way to use the Common Name of a client certificate as an authenticated user in Tomcat. If you know how to configure this on a Tomcat server, or find some current documentation showing how to do so, please create a new issue on github and I’ll add it here.

Assuming you have that all figured out, here’s how you do the client side part using tomcatmanager. I’ve excluded the user and password from these examples. However, it is possible to have a configuration that does both SSL/TLS client authentication and HTTP Basic authentication using a user and password. If you are issuing the keys and certificates from a private certificate authority, you will need to combine the methods above for doing so with the options shown here.

Client authentication uses public key cryptography, where you have a private key that you never share with anyone, and a public key (or certificate in SSL/TLS lingo) that can be freely shared. You can have your key and your certificate in separate files, or they can be combined into a single file.

Warning

When creating a private key you can protect it with a passphrase, which encrypts the private key. To use the key you must enter the passphrase. In order to work with tomcatmanager, the private key for your local certificate must be unencrypted. The Requests library used for network communication does not support using encrypted keys.

Use the --key and --cert options from the command line to specify the private key and associated certificate used to respond to the authentication requests from the server. If you have the key and the certificate in a single file, then omit the --key option and use the combined file with the --cert option:

$ tomcat-manager --key /etc/ssl/mykey --cert /etc/ssl/mycert \
https://www.example.com/manager list

Interactive mode works simiarly, this example shows how to use a combined key and certificate file:

$ tomcat-manager
tomcat-manager>connect --cert /etc/ssl/mycertandkey https://www.example.com/manager
--connected to https://www.example.com/manager authenticated by /etc/ssl/mycertandkey

The TomcatManager.connect() method accepts a cert keyword-only parameter. If your key and certificate are in the same file, pass the filename in that parameter. If they are in separate files, pass a tuple with the cert and the key:

url = "https://www.example.com/manager"
user = "ace"
password = "newenglandclamchowder"
certandkey = ("/etc/ssl/mycert", "/etc/ssl/mykey")
tomcat = tm.TomcatManager()
r = tomcat.connect(url, user, password, cert=certandkey)

API Documentation

Python API documentation for tomcatmanager 7.0.1

tomcatmanager is a command line tool and python library for managing a Tomcat server.

The most important class in the package is TomcatManager. This class connects to a Tomcat Manager web application, allows you to run various commands, and returns the responses to you as an instance of TomcatManagerResponse.

The interactive command line program tomcat-manager provided by this package is an instance of InteractiveTomcatManager. This command line program uses the API documented here, but it not considered part of the published API.

TomcatManager

class tomcatmanager.tomcat_manager.TomcatManager

A class for interacting with the Tomcat Manager web application.

Here’s a summary of the recommended way to use this class with proper exception and error handling. For this example, we’ll use the server_info() method.

import tomcatmanager as tm
url = "http://localhost:808099/manager"
user = "ace"
password = "newenglandclamchowder"
tomcat = tm.TomcatManager()
try:
    r = tomcat.connect(url, user, password)
    if r.ok:
        r = tomcat.server_info()
        if r.ok:
            print(r.server_info)
        else:
            print(f"Error: {r.status_message}")
    else:
        print("not connected")
except Exception as err:
    # handle exception
    print("not connected")

Attributes:

timeout

Seconds to wait before giving up on network operations.

url

Url of the Tomcat Manager web application we are connected to.

user

User we successfully authenticated to the Tomcat Manager web application with.

cert

Client side SSL/TLS certificates we authenticated to the Tomcat Manager web application with.

verify

The certificate authority directory or bundle to use to verify server SSL/TLS certificates.

tomcat_major_minor

If connected to a server, this contains an instance of TomcatMajorMinor describing the major version of Tomcat we are connected to.

is_connected

Does the url point to an actual tomcat server and are the credentials valid?

Methods:

implements(method)

Is a method implemented on the tomcat server we are connected to?

implemented_by(method, tomcat_major_minor)

Check whether a method is implemented by any version of Tomcat.

connect(url[, user, password, cert, verify, ...])

Connect to the manager application running in a Tomcat server.

disconnect()

Disconnect from the manager application running in a Tomcat server.

deploy_localwar(path, warfile[, version, update])

Deploy a warfile from the local file system to the Tomcat server.

deploy_serverwar(path, warfile[, version, ...])

Deploy a warfile from the server file system to the Tomcat server.

deploy_servercontext(path, contextfile[, ...])

Deploy a Tomcat application defined by a context file from the server filesystem to the Tomcat server.

undeploy(path[, version])

Undeploy an application in the Tomcat server.

start(path[, version])

Start an application already deployed in the Tomcat server.

stop(path[, version])

Stop an application already deployed in the Tomcat server.

reload(path[, version])

Stop and start a Tomcat application.

sessions(path[, version])

Get the age of the sessions for an application.

expire(path[, version, idle])

Expire idle sessions.

list()

Get a list of all applications currently installed.

server_info()

Get information about the Tomcat server.

status_xml()

Get server status information in XML format.

vm_info()

Get diagnostic information about the JVM.

thread_dump()

Get a JVM thread dump.

resources([type_])

Get the global JNDI resources

find_leakers()

Get apps that leak memory.

ssl_connector_ciphers()

Get SSL/TLS ciphers configured for each connector.

ssl_connector_certs()

Get the SSL certificate chain currently configured for each virtual host

ssl_connector_trusted_certs()

Get the trusted certificates currently configured for each virtual host

ssl_reload([host])

Reload TLS certificates and keys (but not server.xml) for a specified or all virtual hosts

timeout

Seconds to wait before giving up on network operations. Can be a float or an int. Default is 10. I surely don’t want to wait forever, but if you do, set to 0.

Usage:

>>> import tomcatmanager as tm
>>> tomcat = tm.TomcatManager()
>>> tomcat.timeout = 3.5

Changed in version 3.0.0: Can be a float or int instead of just an int

property url: str

Url of the Tomcat Manager web application we are connected to.

This attribute is set by the connect() method. Look there for more info.

Changed in version 3.0.0: Now a read-only property instead of a read-write attribute.

property user: str

User we successfully authenticated to the Tomcat Manager web application with.

This attribute is set by the connect() method. Look there for more info.

Changed in version 3.0.0: Now a read-only property instead of a read-write attribute.

property cert: str | Tuple[str, str]

Client side SSL/TLS certificates we authenticated to the Tomcat Manager web application with.

This attribute is set by the connect() method. Look there for more info.

New in version 3.0.0.

property verify: str | bool

The certificate authority directory or bundle to use to verify server SSL/TLS certificates. If False no verification is performed.

This attribute is set by the connect() method. Look there for more info.

New in version 3.0.0.

property tomcat_major_minor: TomcatMajorMinor

If connected to a server, this contains an instance of TomcatMajorMinor describing the major version of Tomcat we are connected to.

This attribute is set by the connect() method. Look there for more info.

New in version 3.0.0.

implements(method: Callable | str) bool

Is a method implemented on the tomcat server we are connected to?

Parameters:

method – a method on TomcatManager to check if is implemented

Returns:

True if the method is implemented, False otherwise

Raises:

TomcatNotConnected – if we are not currently connected to a tomcat server

Not all versions of Tomcat implement all of the methods of TomcatManager. Use this to check whether a method on this class is implemented by the version of the Tomcat server we are connected to. The method parameter accepts a string containing the method name or the method itself.

Usage:

import tomcatmanager as tm
tomcat = tm.TomcatManager()
tomcat.connect("http://localhost:8080", "ace", "newenglandclamchowder")
print(tomcat.implements(tomcat.deploy_localwar))

or:

import tomcatmanager as tm
tomcat = tm.TomcatManager()
tomcat.connect("http://localhost:8080", "ace", "newenglandclamchowder")
print(tomcat.implements(tomcat.ssl_reload))

New in version 3.0.0.

classmethod implemented_by(method: Callable | str, tomcat_major_minor: TomcatMajorMinor) bool

Check whether a method is implemented by any version of Tomcat.

Parameters:
  • method – a method on TomcatManager to check

  • tomcat_major_minor – the version of Tomcat to check

Returns:

True if the method is implemented on the given tomcat version.

This method does not require prior connection to a Tomcat server.

Usage:

import tomcatmanager as tm
lowest = tm.TomcatMajorMinor.lowest_supported()
tomcat = tm.TomcatManager()
print(tomcat.implemented_by(tomcat.ssl_reload, lowest))

New in version 3.0.0.

property is_connected: bool

Does the url point to an actual tomcat server and are the credentials valid?

Returns:

True if connected to a tomcat server, otherwise, False.

connect(url: str, user: str = '', password: str = '', *, cert: str | Tuple[str, str] = None, verify: str | bool = True, timeout: float = None) TomcatManagerResponse

Connect to the manager application running in a Tomcat server.

Parameters:
  • url – url where the Tomcat Manager web application is deployed

  • user – (optional) user to authenticate with

  • password – (optional) password to authenticate with

  • cert – client side certificates to use for SSL/TLS authentication

  • verify – verify server SSL/TLS certificates

  • timeout – timeout in seconds for network operations

Returns:

TomcatManagerResponse object with an additional server_info attribute

The server_info attribute of the returned object contains a ServerInfo object, which is a dictionary with some added properties for well-known values returned from the Tomcat server.

This method:

  • sets or changes the url, credentials, and certificates on an existing object

  • provides a convenient mechanism to validate you can actually connect to the server

  • returns a response object that includes information about the server you are connected to

  • allows you to inspect the response so you can see why you can’t connect

Usage

>>> import tomcatmanager as tm
>>> url = "http://localhost:808099/manager"
>>> user = "ace"
>>> password = "newenglandclamchowder"
>>> tomcat = tm.TomcatManager()
>>> try:
...     r = tomcat.connect(url, user, password)
...     if r.ok:
...         print("connected")
...     else:
...         print("not connected")
... except Exception as err:
...    # handle exception
...    print("not connected")
not connected

Many things can go wrong when requesting url’s via http. tomcatmanager uses the requests library for all network communication, and follows that library’s approach for raising exceptions and checking the response to your request. Therefore:

  • Some exceptions will always be raised by this method. If you give a URL where no web server is listening, requests.connections.ConnectionError will be raised.

  • Other exceptions will only be raised if you call TomcatManagerResponse.raise_for_status(). For example, if the credentials are incorrect, you won’t get an exception unless you ask for it.

  • The TomcatManagerResponse.ok attribute is the easiest and most rigerous way to check whether you connected successfully. However, as the example usage above shows, you still have to catch exceptions because requests can raise exceptions from inside the connect() method and this library doesn’t attempt to catch them so that you can do specific error handling if you want to.

All communications between this library and a Tomcat server happen over HTTP, which means there isn’t a persistent connection. A new HTTP GET request is issued for each method call on this object (i.e. deploy_localwar(), stop()). However, the mental model for this library is connection based: use the connect() method to establish the URL and authentication credentials, then call other methods to perform actions on the server you are connected to. If you try and call other methods before you call connect(), TomcatNotConnected will be raised. Because there is no persistent connection of any kind, there is no disconnect method and no cleanup to perform when you are done using a server.

If you discard or don’t save the return object from this method, you can call is_connected() to check if you are connected.

Authentication

The only way to validate the URL and authentication credentials is to make an HTTP request to the server and see if it returns successfully. Internally this method tries to retrieve /manager/text/serverinfo.

Typically authentication is done via user and password. Pass those parameters to utilize HTTP Basic authentication.

To authenticate with a SSL/TLS server using a client certificate and key, pass the path to a single file containing the private key and certificate in the cert parameter. As an alternative, you can pass a tuple containing the path to the certificate, and the path to the key.

Warning

The private key for your local certificate must be unencrypted. The Requests library used for network communication does not support using encrypted keys.

If the URL uses the https protocol, the default behavior is to validate the server SSL/TLS certificate chain.

To validate with your own certificate authority bundle, set the verify parameter to the path to a certificate authority bundle file or a directory of certificates of trusted certificate authorities. You can disable server certificate validation by setting verify to False.

See Authentication for more details.

Side Effects

Passing a timeout parameter to this method has the side effect of setting the timeout attribute on this object.

Requesting url’s via http can also result in redirection to another url. If that occurs, the new url, not the one you passed, will be stored in the url attribute.

If you pass user and password credentials and the connection is successful, the user will be stored in the user attribute.

If you pass an authentication key and certificate in the cert parameter and the connection is successful, the information will be stored in the cert attribute.

Upon successful connection, an instance of TomcatMajorMinor will be stored in tomcat_major_minor indicating the major version of Tomcat running on the server. Further details about the server are available in the server_info attribute of the returned response.

Changed in version 3.0.0:

disconnect()

Disconnect from the manager application running in a Tomcat server.

Returns:

always returns True

New in version 7.0.0.

deploy_localwar(path: str, warfile: str, version: str = None, update: bool = False) TomcatManagerResponse

Deploy a warfile from the local file system to the Tomcat server.

Parameters:
  • path – The path on the server to deploy this war to, i.e. /sampleapp

  • warfile – The path (specified using your local operating system convention) to a war file on the local file system. You can also pass a stream or file-like object. This will be sent to the server for deployment.

  • version – (optional) For tomcat parallel deployments, the version string to associate with this deployment

  • update – (optional) Whether to undeploy the existing path first (default False)

Returns:

TomcatManagerResponse object

Raises:

ValueError – if no path is specified or if no warfile is specified

deploy_serverwar(path: str, warfile: str, version: str = None, update: bool = False) TomcatManagerResponse

Deploy a warfile from the server file system to the Tomcat server.

Parameters:
  • path – The path on the server to deploy this war to, i.e. /sampleapp

  • warfile – The java-style path (use slashes not backslashes) to the war file on the server. Don’t include file: at the beginning.

  • version – (optional) For tomcat parallel deployments, the version string to associate with this deployment

  • update – (optional) Whether to undeploy the existing path first (default False)

Returns:

TomcatManagerResponse object

Raises:

ValueError – if no path is given or if no warfile is given

deploy_servercontext(path: str, contextfile: str, warfile: str = None, version: str = None, update: bool = False) TomcatManagerResponse

Deploy a Tomcat application defined by a context file from the server filesystem to the Tomcat server.

Parameters:
  • path – The path on the server to deploy this war to, i.e. /sampleapp

  • contextfile – The java-style path (use slashes not backslashes) to the context file on the server. Don’t include file: at the beginning.

  • warfile – (optional) The java-style path (use slashes not backslashes) to the war file on the server. Don’t include file: at the beginning.

  • version – (optional) For tomcat parallel deployments, the version string to associate with this deployment

  • update – (optional) Whether to undeploy the existing path first (default False)

Returns:

TomcatManagerResponse object

Raises:

ValueError – if no path is given or if no contextfile is given

undeploy(path: str, version: str = None) TomcatManagerResponse

Undeploy an application in the Tomcat server.

Parameters:
  • path – The path of the application to undeploy

  • version – (optional) The version string of the app to undeploy

Returns:

TomcatManagerResponse object

Raises:

ValueError – if no path is specified

If the application was deployed with a version string, it must be specified in order to undeploy the application.

start(path: str, version: str = None) TomcatManagerResponse

Start an application already deployed in the Tomcat server.

Parameters:
  • path – The path of the application to start

  • version – (optional) The version string of the app to start

Returns:

TomcatManagerResponse object

Raises:

ValueError – if no path is specified

If the application was deployed with a version string, it must be specified in order to start the application.

stop(path: str, version: str = None) TomcatManagerResponse

Stop an application already deployed in the Tomcat server.

Parameters:
  • path – The path of the application to stop

  • version – (optional) The version string of the app to stop

Returns:

TomcatManagerResponse object

Raises:

ValueError – if no path is specified

If the application was deployed with a version string, it must be specified in order to stop the application.

reload(path: str, version: str = None) TomcatManagerResponse

Stop and start a Tomcat application.

Parameters:
  • path – The path of the application to reload

  • version – (optional) The version string of the app to reload

Returns:

TomcatManagerResponse object

Raises:

ValueError – if no path is specified

If the application was deployed with a version string, it must be specified in order to reload the application.

sessions(path: str, version: str = None) TomcatManagerResponse

Get the age of the sessions for an application.

Parameters:
  • path – The path of the application to get session information about

  • version – (optional) The version string of the app to get session information about

Returns:

TomcatManagerResponse object with the session summary in both the result attribute and the sessions attribute

Raises:

ValueError – if no path is specified

Usage:

>>> tomcat = getfixture("tomcat")
>>> r = tomcat.sessions("/manager")
>>> if r.ok:
...     session_data = r.sessions
expire(path: str, version: str = None, idle: Any = None) TomcatManagerResponse

Expire idle sessions.

Parameters:
  • path – the path to the app on the server whose sessions you want to expire

  • idle – sessions idle for more than this number of minutes will be expired. Use idle=0 to expire all sessions.

Returns:

TomcatManagerResponse object with the session summary in both the result attribute and the sessions attribute

Raises:

ValueError – if no path is specified

Usage:

>>> tomcat = getfixture("tomcat")
>>> r = tomcat.expire("/manager", idle=15)
>>> if r.ok:
...     expiration_data = r.sessions
list() TomcatManagerResponse

Get a list of all applications currently installed.

Returns:

TomcatManagerResponse object with an additional apps attribute which contains a list of TomcatApplication objects

Usage:

>>> import tomcatmanager as tm
>>> tomcat = getfixture("tomcat")
>>> r = tomcat.list()
>>> if r.ok:
...     running = filter(lambda app: app.state == tm.ApplicationState.RUNNING, r.apps)
server_info() TomcatManagerResponse

Get information about the Tomcat server.

Returns:

TomcatManagerResponse object with an additional server_info attribute

The server_info attribute contains a ServerInfo object, which is a dictionary with some added properties for well-known values returned from the Tomcat server.

Usage:

>>> tomcat = getfixture("tomcat")
>>> r = tomcat.server_info()
>>> if r.ok:
...     r.server_info["OS Name"] == r.server_info.os_name
True
status_xml() TomcatManagerResponse

Get server status information in XML format.

Returns:

TomcatManagerResponse object with an additional status_xml attribute

Usage:

>>> import xml.etree.ElementTree as ET
>>> tomcat = getfixture("tomcat")
>>> r = tomcat.status_xml()
>>> if r.ok:
...     root = ET.fromstring(r.status_xml)
...     mem = root.find("jvm/memory")
...     print(f"Free Memory = {mem.attrib['free']}") 
Free Memory ...
vm_info() TomcatManagerResponse

Get diagnostic information about the JVM.

Returns:

TomcatManagerResponse object with an additional vm_info attribute

thread_dump() TomcatManagerResponse

Get a JVM thread dump.

Returns:

TomcatManagerResponse object with an additional thread_dump attribute

resources(type_: str = None) TomcatManagerResponse

Get the global JNDI resources

Parameters:

type – (optional) Fully qualified java class name of the resource type you are interested in. For example, pass javax.sql.DataSource to acquire the names of all available JDBC data sources.

Returns:

TomcatManagerResponse object with an additional resources attribute.

Usage:

>>> tomcat = getfixture("tomcat")
>>> r = tomcat.resources()
>>> if r.ok:
...     print(r.resources)
{'UserDatabase': 'org.apache.catalina.users.MemoryUserDatabase'}

resources is a dictionary with the resource name as the key and the class name as the value.

find_leakers() TomcatManagerResponse

Get apps that leak memory.

Returns:

TomcatManagerResponse object with an additional leakers attribute

The leakers attribute contains a list of paths of applications which leak memory.

This command triggers a full garbage collection on the server. Use with extreme caution on production systems.

Explicity triggering a full garbage collection from code is documented to be unreliable. Furthermore, depending on the jvm, there are options to disable explicit GC triggering, like -XX:+DisableExplicitGC. If you want to make sure this command triggered a full GC, you will have to verify using something like GC logging or JConsole.

The Tomcat Manager documentation says the server can return duplicates in this list if the app has been reloaded and was leaking both before and after the reload. The list returned by the leakers attribute will have no duplicates in it.

Usage:

>>> tomcat = getfixture("tomcat")
>>> r = tomcat.find_leakers()
>>> if r.ok:
...     cnt = len(r.leakers)
... else:
...     cnt = 0
ssl_connector_ciphers() TomcatManagerResponse

Get SSL/TLS ciphers configured for each connector.

Returns:

TomcatManagerResponse object with an additional ssl_connector_ciphers attribute

ssl_connector_certs() TomcatManagerResponse

Get the SSL certificate chain currently configured for each virtual host

Returns:

TomcatManagerResponse object with an additional ssl_connector_certs attribute

ssl_connector_trusted_certs() TomcatManagerResponse

Get the trusted certificates currently configured for each virtual host

Returns:

TomcatManagerResponse object with an additional ssl_connector_trusted_certs attribute

ssl_reload(host: str = None) TomcatManagerResponse

Reload TLS certificates and keys (but not server.xml) for a specified or all virtual hosts

Parameters:

host – (optional) Host name to reload, if omitted, reload all virtual hosts

Returns:

TomcatManagerResponse object

TomcatManagerResponse

class tomcatmanager.models.TomcatManagerResponse(response: Response = None)

Returned as the response for TomcatManager commands.

After running a command, it’s a good idea to check and make sure that the command completed succesfully before relying on the results:

>>> import tomcatmanager as tm
>>> tomcat = getfixture("tomcat")
>>> try:
...     r = tomcat.server_info()
...     r.raise_for_status()
...     if r.ok:
...         print(f"Operating System: {r.server_info.os_name}")
...     else:
...         print(f"Error: {r.status_message}")
... except Exception as err:
...     # handle exception
...     pass
Operating System: ...
status_code

Status of the Tomcat Manager command from the first line of text.

The preferred way to check for success is to use the ok() method, because it checks for http errors as well as tomcat errors. However, if you want specific access to the status of the tomcat command, use this method.

The status codes are enumerated in StatusCode.

>>> import tomcatmanager as tm
>>> tomcat = getfixture("tomcat")
>>> r = tomcat.server_info()
>>> r.status_code == tm.StatusCode.OK
True
status_message

The message on the first line of the response from the Tomcat Server.

result

The text of the response from the Tomcat server, without the first line (which contains the status code and message).

property ok
Returns:

True if the request completed with no errors.

For this property to return True:

  • The HTTP request must return a status code of 200 OK

  • The first line of the response from the Tomcat Manager web application must begin with OK.

raise_for_status()

Raise exceptions for server errors.

First this method calls requests.Response.raise_for_status() which raises exceptions if a 4xx or 5xx response is received from the server.

If that doesn’t raise anything, then it raises a TomcatError if there is not an OK response from the first line of text back from the Tomcat Manager web app.

property response: Response

The server’s response to an HTTP request.

TomcatManager uses the excellent Requests package for HTTP communication. This property returns the requests.Response object which contains the server’s response to the HTTP request.

Of particular use is requests.Response.text which contains the content of the response in unicode. If you want raw access to the content returned by the Tomcat Server, this is where you can get it.

TomcatApplication

class tomcatmanager.models.TomcatApplication

Discrete data about an application running inside a Tomcat Server.

A list of these objects is returned by TomcatManager.list().

classmethod sort_by_state_by_path_by_version(app: TomcatApplication)

Create a key usable by sort to sort by state, by path, by version.

classmethod sort_by_path_by_version_by_state(app: TomcatApplication)

Create a key usable by sort to sort by path, by version, by state

parse(line: str)

Parse a line from the server into this object.

Param:

line - the line of text from Tomcat Manager describing a deployed application

Tomcat Manager outputs a line like this for each application:

/shiny:running:0:shiny##v2.0.6

The data elements in this line can be described as:

{path}:{state}:{sessions}:{directory}##{version}

Where version and the two hash marks that precede it are optional.

property path

The context path, or relative URL, where this app is available on the server.

property state

The current state of the application.

tomcatmanager.ApplicationState is an enum of the values for this property.

>>> import tomcatmanager as tm
>>> tm.ApplicationState.STOPPED
<ApplicationState.STOPPED: 'stopped'>
>>> tm.ApplicationState.RUNNING
<ApplicationState.RUNNING: 'running'>
property sessions

The number of currently active sessions.

property directory

The directory on the server where this application resides.

property version

The version of the application given when it was deployed.

If deployed without a version, this property returns None.

property directory_and_version

Combine directory and version together.

Tomcat provides this information as {directory} if there was no version specified when the application was deployed, or {directory}##{version} if the version was specified.

This method has the logic to determine if version was specified or not.

ApplicationState

class tomcatmanager.models.ApplicationState(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

An enumeration of the various tomcat application states.

New in version 2.0.0.

RUNNING = 'running'
STOPPED = 'stopped'
classmethod parse(state: str)

Return one of the enums from a string sent by the Tomcat Manager web application.

Parameters:

state (str) – the string value of the application state from the tomcat server

Returns:

ApplicationState instance

Return type:

tomcatmanager.models.ApplicationState

Raises:

ValueError – if the string does not represent a known application state

StatusCode

class tomcatmanager.models.StatusCode(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

An enumeration of the various Tomcat Manager web application status codes

tomcatmanager uses the excellent requests library, which uses a custom LookupDict class to store HTTP status codes in a dictionary. After much debate on whether we should do it the requests way, or a more pythonic way, I chose to use a native Enum class instead.

New in version 2.0.0.

OK = 'OK'
FAIL = 'FAIL'
NOTFOUND = 'NOTFOUND'
classmethod parse(code: str)

Return one of the enums from a string sent by the Tomcat Manager web application.

Parameters:

state (str) – the string value of the status code from the tomcat server

Returns:

StatusCode instance

Return type:

tomcatmanager.models.StatusCode

Raises:

ValueError – if the string does not represent a known status code

ServerInfo

class tomcatmanager.models.ServerInfo(*args, **kwargs)

Discrete data about the Tomcat server.

This object is a dictionary of keys and values as returned from the Tomcat server. It also has properties for well-known values.

Usage:

>>> tomcat = getfixture('tomcat')
>>> r = tomcat.server_info()
>>> r.server_info['OS Architecture'] 
'...'
>>> r.server_info.jvm_vendor 
'...'
property tomcat_major_minor: TomcatMajorMinor

An instance of TomcatMajorMinor indicating which major and minor version of Tomcat is running on the server.

This value is computed, not received from the server, and therefore does not show up in the dictionary, ie server_info["tomcat_major_minor"] does not exist.

New in version 3.0.0.

property tomcat_version

The tomcat version string.

property os_name

The operating system name.

property os_version

The operating system version.

property os_architecture

The operating system architecture.

property jvm_version

The java virtual machine version string.

property jvm_vendor

The java virtual machine vendor.

TomcatMajorMinor

class tomcatmanager.models.TomcatMajorMinor(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

An enumeration of the supported Tomcat major and minor version numbers

Major and Minor have the meanings defined at https://semver.org.

This enumeration includes a value VNEXT, so that this module can mostly keep working when accessing a version of Tomcat that the module doesn’t officially support yet.

It also includes a value UNSUPPORTED, for older versions of Tomcat that are unknown to this module.

New in version 3.0.0.

V8_5 = '8.5'
V9_0 = '9.0'
V10_0 = '10.0'
V10_1 = '10.1'
VNEXT = 'next'
UNSUPPORTED = 'unsupported'
classmethod parse(version_string: str) TomcatMajorMinor

Return one of the enums from a string sent by the Tomcat Manager web application.

Parameters:

version_string – the string value of the application state from the tomcat server

Returns:

TomcatMajorMinor instance

Raises:

ValueError – if the version string does not represent a known app

static supported() List

Return the list of officially supported Tomcat major versions

classmethod lowest_supported() TomcatMajorMinor

Return the lowest officially supported Tomcat major version

classmethod highest_supported() TomcatMajorMinor

Return the highest officially supported Tomcat major version

This does not include TomcatMajorMinor.VNEXT, which exists to ensure this module mostly works on future versions of tomcat before official support is added.

TomcatError

class tomcatmanager.models.TomcatError

Raised when the Tomcat Server responds with an error.

TomcatNotConnected

class tomcatmanager.models.TomcatNotConnected

Raised when a method is called on TomcatManager without the connect() method being called first.

New in version 3.0.0.

TomcatNotImplementedError

class tomcatmanager.models.TomcatNotImplementedError

Raised when a Tomcat Manager web application does not support a python API call.

As of version 6.0.0, all supported Tomcat Manager web application versions support all python API calls: therefore this error will never be raised.

It is not deprecated in case it is needed in future versions.

See Differences in Tomcat Versions for more information.

New in version 3.0.0.

Migrating to version 2.x

Version 2.0 made some changes to the API for Tomcat Manager.

Status Codes

In version 1.x tomcatmanager.models.status_codes was an instance of AttrDict, a class from the attrdict library. This library has been sunset: on python 3.9 it generates warnings from deprecated usage of the standard library. It will break on python 3.10.

Most methods on TomcatManager return a TomcatManagerResponse. You should be using the TomcatManagerResponse.ok property to determine whether your command completed successfully. This method checks both the HTTP response code, as well as parsing the status text received from the Tomcat Manager web application. If your code does this, migrating to 2.x will be very easy, because you won’t have to change much of anything. The following code works in both 1.x and 2.x:

import tomcatmanager as tm
tomcat = tm.TomcatManager()
tomcat.connect('http://localhost:8080/manager')
try:
    r = tomcat.server_info()
    r.raise_for_status()
    if r.ok:
        print(r.server_info.os_name)
    else:
        print(f"Error: {r.status_message}")
except Exception as err:
    # handle exception
    pass

If you are doing alternative checking like this:

import tomcatmanager as tm
tomcat = tm.TomcatManager()
tomcat.connect('http://localhost:8080/manager')
try:
    r = tomcat.server_info()
    r.raise_for_status()
    if r.status_code == tm.status_codes.notfound:
        print("Tomcat Manager web application was not found")

you might consider this a good opportunity to update your code to check TomcatManagerResponse.ok instead. If that doesn’t work for you, then you’ll have to change it to be something like this:

import tomcatmanager as tm
tomcat = tm.TomcatManager()
tomcat.connect('http://localhost:8080/manager')
try:
    r = tomcat.server_info()
    r.raise_for_status()
    if r.status_code == tm.StatusCode.NOTFOUND:
        print("Tomcat Manager web application was not found")

See StatusCode for the list of all available status codes.

Application State

In version 1.x, tomcatmanager.models.application_states was an instance of AttrDict, a class from the attrdict library. This library has been sunset: on python 3.9 it generates warnings from deprecated usage of the standard library. It will break on python 3.10.

The state attribute of the TomcatApplication class could be used like this:

import tomcatmanager as tm
tomcat = tm.TomcatManager()
tomcat.connect('http://localhost:8080/manager')
r = tomcat.list()
if r.ok:
  running = filter(lambda app: app.state == tm.application_states.running, r.apps)

In version 2.x, tomcatmanager.models.application_states has been replaced with an enum called ApplicationState. The equivilent code in version 2.x is:

import tomcatmanager as tm
tomcat = tm.TomcatManager()
tomcat.connect('http://localhost:8080/manager')
r = tomcat.list()
if r.ok:
    running = filter(lambda app: app.state == tm.ApplicationState.RUNNING, r.apps)

See ApplicationState for documentation on all the possible values.

Migrating to version 3.x

Version 3 of tomcatmanager adds several new capabilities, and makes a few breaking changes. See the Changelog for a short summary. This document explains the reasoning behind the changes and includes specific guidance for migrating from version 2.

Version 3 contains two new capabilities. First, additional SSL/TLS server certificate verification options and client authentication options have been added. These new capabilities are described in Authentication and are implemented in a completely backwards compatible way. Pass additional keyword-only parameters to the TomcatManager.connect() method to access these features.

Second, not all supported versions Tomcat (and the Manager application included in the distribution), implement the same set of manager commands. For example, the sslReload command is implemented in Tomcat 10.x, but not in Tomcat 7.x. If you called the TomcatManager.ssl_reload() method after connecting to a Tomcat 7.x server, an exception was raised, but it was a HTTP error and you couldn’t really tell that the problem was that this command wasn’t implemented by that server. Exposing a reliable mechanism to raise new exceptions in this scenario required some breaking changes.

HTTP is a stateless protocol. Web developers have come up with various strategies for preserving state across multiple requests, including session tokens and cookies. Tomcatmanager 2.x had no reason to preserve state across multiple calls to the server. When you called the TomcatManager.connect() method it made a HTTP request to the url attribute, and created a HTTP Basic authentication header using the contents of the user attribute. Because there was no state, you could freely modify either of those attributes at any time, and the HTTP request would throw exceptions if errors occured.

In tomcatmanager 3.x we need to know what version of the server is on the other end of the line. We could either have a super-chatty network exchange and query the server before every request to figure out what version it is, or we can figure it on our first request, and then preserve the state across all of our other requests. I chose the latter.

This means that the original philosophy for connect needed to be modified. In tomcatmanager 2.x you could change the url it didn’t matter. In tomcatmanager 3.x if you change the url or the user, our preserved state needs to be invalidated. To accommodate this change in approach, some breaking changes were made to the API in tomcatmanager 3.x:

If you are assigning values to TomcatManager.user or TomcatManager.url, I’ve got bad news, your code will break badly. The good news is that these should be easy to find and fix. You’ll have to pass these parameters to the TomcatManager.connect() method now.

That’s it for migrating. There are a bunch of new features in tomcatmanager 3.x which you can take advantage of (see the Changelog), but none of them will break your existing code.

Migrating to version 4.x

The only change from 3.x to 4.x is that Tomcat 7 is no longer supported. The Tomcat project ended support for Tomcat 7 on 31 March 2021, and in early July 2021 the download and documentation pages were removed from the website.

If you require Tomcat 7 support, use version 3.x.

Migrating to version 5.x

Version 5.0 adds support for Python 3.10 and drops support for Python 3.6.

No API changes were made in this version, so you don’t have to make any changes to your code. The change in major version number with no API change was done so that if you are using this library against a single version of Tomcat, and you specify your setup.py dependency rules like:

setup(
...
    install_requires=["tomcatmanager>=3,<4"]
...
)

you won’t have to worry about a future release of this software breaking your configuration.

Migrating to version 6.x

Version 6.0 adds support for Python 3.11 and Tomcat 10.1. It drops support for Tomcat 8.0.

No API changes were made in this version, so you don’t have to make any changes to your code. The change in major version number with no API change was done to prevent your application breaking by a new release of this library, as long as you specify your dependencies properly. See Specifying As A Dependency for more information.

As of version 6.0.0, all supported Tomcat Manager web application versions support all python API calls. Therefore, this version of the library will not raise TomcatNotImplementedError exceptions. But, you should still check for them. See Differences in Tomcat Versions for more information.

Migrating to version 7.x

Version 7.0 drops support for Python 3.7 and adds support for Python 3.12.

There is one new method in this release: TomcatManager.disconnect(). Nothing else in the API has changed, so you won’t have to update your code to upgrade to this version.

The tomcat-manager application has many improvements, but none of them impact the API.

Contributing

Get Source Code

Clone the repo from github:

$ git clone git@github.com:tomcatmanager/tomcatmanager.git

Create Python Environments

tomcatmanager uses tox to run the test suite against multiple python versions. tox expects that when it runs python3.9 it will actually get a python from the 3.9.x series.

I recommend using pyenv with the pyenv-virtualenv plugin to manage these various python versions. If you are a Windows user, pyenv won’t work for you, you’ll probably have to use conda.

This distribution includes a shell script build-pyenvs.sh which automates the creation of these environments.

If you prefer to create these virtual envs by hand, do the following:

$ cd tomcatmanager
$ pyenv install 3.12.0
$ pyenv virtualenv -p python3.12 3.12.0 tomcatmanager-3.12
$ pyenv install 3.11.5
$ pyenv virtualenv -p python3.11 3.11.5 tomcatmanager-3.11
$ pyenv install 3.10.13
$ pyenv virtualenv -p python3.10 3.10.13 tomcatmanager-3.10
$ pyenv install 3.9.18
$ pyenv virtualenv -p python3.9 3.9.18 tomcatmanager-3.9
$ pyenv install 3.8.18
$ pyenv virtualenv -p python3.8 3.8.18 tomcatmanager-3.8

Now set pyenv to make all five of those available at the same time:

$ pyenv local tomcatmanager-3.12 tomcatmanager-3.11 tomcatmanager-3.10 tomcatmanager-3.9 tomcatmanager-3.8

Whether you ran the script, or did it by hand, you now have isolated virtualenvs for each of the minor python versions. This table shows various python commands, the version of python which will be executed, and the virtualenv it will utilize.

Command

python

virtualenv

python

3.12.0

tomcatmanager-3.12

python3

3.12.0

tomcatmanager-3.12

python3.12

3.12.0

tomcatmanager-3.12

python3.11

3.11.5

tomcatmanager-3.11

python3.10

3.10.13

tomcatmanager-3.10

python3.9

3.9.18

tomcatmanager-3.9

python3.8

3.8.18

tomcatmanager-3.8

pip

3.11.5

tomcatmanager-3.11

pip3

3.11.5

tomcatmanager-3.11

pip3.11

3.11.5

tomcatmanager-3.11

pip3.10

3.10.13

tomcatmanager-3.10

pip3.9

3.9.18

tomcatmanager-3.9

pip3.8

3.8.18

tomcatmanager-3.8

Install Dependencies

Now install all the development dependencies:

$ pip install -e .[dev]

This installs the tomcatmanager package “in-place”, so the package points to the source code instead of copying files to the python site-packages folder.

All the dependencies now have been installed in the tomcatmanager-3.12 virtualenv. If you want to work in other virtualenvs, you’ll need to manually select it, and install again:

$ pyenv shell tomcatmanager-3.10
$ pip install -e .[dev]

Branches, Tags, and Versions

This project uses a simplified version of the git flow branching strategy. We don’t use release branches, and we generally don’t do hotfixes, so we don’t have any of those branches either. The main branch always contains the latest release of the code uploaded to PyPI, with a tag for the version number of that release.

The develop branch is where all the action occurs. Feature branches are welcome. When it’s time for a release, we merge develop into main.

This project uses semantic versioning.

When this library adds support for a new version of Tomcat or Python, we increment the minor version number. However, if support for these new versions requires API changes incompatible with prior releases of this software, then we increment the major version number.

When this library drops support for a version of Tomcat or Python, we increment the major version number. For example, when this project dropped support for Python 3.6, we released that version as 5.0.0 instead of 4.1.0, even though there were no incompatible API changes.

These versioning rules were chosen so that if you are using this library against a single version of Tomcat, and you specify your pyproject.toml dependency rules like:

[project]
dependencies = [
 "tomcatmanager>=4,<5"
]

you won’t have to worry about a future release of this software breaking your setup.

Invoking Common Development Tasks

This project uses many other python modules for various development tasks, including testing, rendering documentation, and building and distributing releases. These modules can be configured many different ways, which can make it difficult to learn the specific incantations required for each project you are familiar with.

This project uses invoke to provide a clean, high level interface for these development tasks. To see the full list of functions available:

$ invoke -l

You can run multiple tasks in a single invocation, for example:

$ invoke clean docs build

That one command will remove all superflous cache, testing, and build files, render the documentation, and build a source distribution and a wheel distribution.

To make it easy to check everything before you commit, you can just type:

$ invoke check
...
$ echo $?
0

and it will test, lint, and check the format of all the code and the documentation. If this doesn’t complete everything successfully then you still need to fix some stuff before you commit or submit a pull request. In this context, complete everything successfully means: all tests pass, lint returns a perfect score, doc8 finds no errors, etc.

To see what is actually getting executed by invoke, check the tasks.py file.

Testing

Unit testing provides reliability and consistency in released software. This project has 100% unit test coverage. Pull requests which reduce test coverage will not be merged.

This repository has Github Actions configured to run tests when you push or merge a pull request. Any push triggers a test run against all supported versions of python in a linux environment. Any pull request triggers a test run against all supported versions of python on all supported operating systems.

You can run the tests against all the supported versions of python using tox:

$ tox

tox expects that when it runs python3.9 it will actually get a python from the 3.9.x series. That’s why we set up the various python environments earlier.

If you just want to run the tests in your current python environment, use pytest:

$ pytest

This runs all the test in tests/ and also runs doctests in tomcatmanager/ and docs/.

You can speed up the test suite by using pytest-xdist to parallelize the tests across the number of cores you have:

$ pip install pytest-xdist
$ pytest -n8

To ensure the tests can run without an external dependencies, this project includes a mock server for each supported version of Tomcat. This speeds up testing considerably and also allows you to parallelize tests using python-xdist.

By default, pytest runs the mock server corresponding to the latest supported version of Tomcat. If you want to test against a different mock server, do something like:

$ pytest --mocktomcat 9.0

Look in conftest.py to see how these servers are implemented and launched.

When you run the tests with tox, the test suite runs against each supported version of Tomcat using each supported version of Python.

In many of the doctests you’ll see something like:

>>> tomcat = getfixture("tomcat")

This getfixture() helper imports fixtures defined in conftest.py, which has several benefits:

  • reduces the amount of redundant code in doctests which shows connecting to a tomcat server and handling exceptions

  • allows doctests to execute against a mock tomcat server

Testing Against A Real Server

If you wish, you can run the test suite against a real Tomcat Server instead of against the mock server included in this distribution. Running the test suite will deploy and undeploy an app hundreds of times, and will definitely trigger garbage collection, so you might not want to run it against a production server.

It’s also slow (which is why the tests normally run against a mock server). When I run the test suite against a stock Tomcat on a Linode with 2 cores and 4GB of memory it takes approximately 3 minutes to complete. I don’t think throwing more CPU at this would make it any faster: during the run of the test suite the Tomcat Server never consumes more than a few percent of the CPU capacity.

You must prepare some files on the server in order for the test suite to run successfully. Some of the tests instruct the Tomcat Server to deploy an application from a warfile stored on the server. I suggest you use the minimal application included in this distribution at tomcatmanager/tests/war/sample.war, but you can use any valid war file. Put this file in some directory on the server; I typically put it in /tmp/sample.war.

You must also construct a minimal context file on the server. You can see an example of such a context file in tomcatmanager/tests/war/context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Context configuration file for my web application -->
<Context path='/ignored' docBase='/tmp/sample.war'>
</Context>

The docBase attribute must point to a valid war file or the tests will fail. It can be the same minimal war file you already put on the server. The path attribute is ignored for context files that are not visible to Tomcat when it starts up, so it doesn’t matter what you have there. I typically put this context file at /tmp/context.xml.

You will also need:

  • the url where the manager app of your Tomcat Server is available

  • a user with the manager-script role

  • the password for the aforementioned user

With all these prerequisites ready, you can feed them to pytest as shown:

$ pytest --url=http://localhost:8080/manager --user=ace \
--password=newenglandclamchowder --warfile=/tmp/sample.war \
--contextfile=/tmp/context.xml

If your tomcat server uses SSL/TLS client certificates for authentication, you can specify those certificates instead of a user and password:

$ pytest --url=https://localhost:8088/manager --cert=/path/to/cert.file \
--key=/path/to/key.file --warfile=/tmp/sample.war --contextfile=/tmp/context.xml

If your certificate and key are in the same file, pass that file using the --cert command line option.

Warning

The private key to your local certificate must be unencrypted. The Requests library used for network communication does not support using encrypted keys.

Warning

If you test against a real Tomcat server, you should not use the pytest-xdist plugin to parallelize testing across multiple CPUs or many platforms. Many of the tests depend on deploying and undeploying an app at a specific path, and that path is shared across the entire test suite. It wouldn’t help much anyway because the testing is constrained by the speed of the Tomcat server.

If you kill the test suite in the middle of a run, you may leave the test application deployed in your tomcat server. If this happens, you must undeploy it before rerunning the test suite or you will get lots of errors.

When the test suite deploys applications, it will be at the path returned by the safe_path fixture in conftest.py. You can modify that fixture if for some reason you need to deploy at a different path.

Code Quality

Use pylint to check code quality. The default pylint config file pylintrc can be used for both the tests and package:

$ pylint src tests

You are welcome to use the pylint comment directives to disable certain messages in the code, but pull requests containing these directives will be carefully scrutinized.

Code Formatting

Use ruff to format your code. We use the default configuration, including a line length of 88 characters.

To format all the code in the project using ruff, do:

$ ruff format *.py tests src docs

You can check whether ruff would make any formatting changes to the source code by:

$ ruff format --check *.py tests src docs

Ruff integrates with many common editors and IDE’s, that’s the easiest way to ensure that your code is always formatted.

Please format the code in your PR using ruff before submitting it, this project is configured to not allow merges if ruff format would change anything.

Punctuation and Capitalization for Users

Messages generated by InteractiveTomcatManager are intended for consumption by users, rather than developers.

Usage messages for individual commands are in all lower case letters with no periods. If the help for a particular option contains multiple phrases, separate them with a semi-colon. This matches the style of argparse.ArgumentParser. For example the message generated for the -h option is an uncapitalized phrase with no period. ArgumentParser epilogs should be sentences with capitalized first letters.

Error messages are in all lower case letters with no periods. This matches the style of the errors generated by argparse.ArgumentParser.

Command descriptions as shown by the help command come from the docstring for the associated method. For example the description shown for the deploy command comes from the the docstring for do_deploy. The code assumes these docstrings are a single line. These command descriptions are all lower case letters with no periods. ArgumentParser objects should get the first line of the docstring to use for the description, so that connect -h always shows the same description as help.

Documentation in /docs is written in sentences with capitalized first letters.

Punctuation and Capitalization for Developers

Docstrings in TomcatManager and other associated classes are written in sentences with capitalized first letters. This matches the style that Sphinx uses to render the documentation and ensures that all html documentation (user and api) follows the same style.

Documentation

Documentation is not an afterthought for this project. All PR’s must include relevant documentation or they will be rejected.

The documentation is written in reStructured Test, and is assembled from both the docs/ directory and from the docstrings in the code. We use Sphinx formatted docstrings. We encourage references to other methods and classes in docstrings, and choose to optimize docstrings for clarity and usefulness in the rendered output rather than ease of reading in the source code.

The documentation is indented using four spaces, the same as the python code.

The code includes type hints as a convenience, but does not provide stub files nor do we use mypy to check for proper static typing. Our philosophy is that the dynamic nature of Python is a benefit and we shouldn’t impose static type checking, but annotations of expected types can be helpful for documentation purposes.

Sphinx transforms the documentation source files into html:

$ cd docs
$ make html

The output will be in docs/build/html. We treat warnings as errors, and the documentation has none. Pull requests which generate errors when the documentation is build will be rejected.

If you are doing a lot of documentation work, the sphinx-autobuild module has been integrated. Type:

$ cd docs
$ make livehtml

Then point your browser at http://localhost:8000 to see the documentation automatically rebuilt as you save your changes.

Use doc8 to check documentation quality:

$ doc8 docs README.rst CONTRIBUTING.rst CHANGELOG.rst

This project is configured to prevent merges to the main or develop branch if doc8 returns any errors.

When code is pushed to the main branch, which only happens when we cut a new release, the documentation is automatically built and deployed to https://tomcatmanager.readthedocs.io/en/stable/. When code is pushed to the develop branch, the documentation is automatically built and deployed to https://tomcatmanager.readthedocs.io/en/develop/.

Make a Release

To make a release and deploy it to PyPI, do the following:

  1. Merge everything to be included in the release into the develop branch.

  2. Run tox to make sure the tests pass in all the supported python versions.

  3. Review and update CHANGELOG.rst.

  4. Update and close the milestone corresponding to the release at https://github.com/tomcatmanager/tomcatmanager/milestones

  5. Push the develop branch to github.

  6. Tag the develop branch with the new version number and push the tag

  7. Create a pull request on github to merge the develop branch into main. Wait for the checks to pass.

  8. Merge the develop branch into the main branch and close the pull request.

  9. Create a new release on Github summarizing the changelog

  10. Change to the main branch.

  11. Install the released version by pip install -e .[dev]

  12. Build source distribution, wheel distribution, and upload them to testpypi:

    $ invoke testpypi
    
  13. Build source distribution, wheel distribution, and upload them to pypi:

    $ invoke pypi
    
  14. Docs are automatically deployed to http://tomcatmanager.readthedocs.io/en/stable/. Make sure they look good. Add a “Version” in readthedocs which points to the tag you just created. Prune old versions as necessary.

  15. Switch back to the develop branch.

  16. Add an Unreleased section to the top of CHANGELOG.rst. Push the change to github.

Changelog

All notable changes to tomcatmanager are documented in this file.

This project uses Semantic Versioning and the format of this file follows recommendations from Keep a Changelog.

7.0.1 (2023-12-02)

Fixed
  • fix triggers and other errors to ensure documentation builds automatically on readthedocs.io

7.0.0 (2023-12-02)

Added
  • Support for Python 3.12

  • Support for themes in tomcat-manager, which can produce styled and colored output

    • New theme setting to choose which theme to use

    • New command line option --theme to set theme from command line

    • New environment variable TOMCATMANAGER_THEME to set theme from environment

    • New theme command for users to list, create, edit, and delete themes

    • Theme gallery which shows themes from an online gallery. Themes can be added and updated in the gallery independent of tomcat-manager releases.

    • Two built-in themes, default-light, and default-dark

    • New command line option --theme-dir to show the full path to the user theme directory

  • New command line option --noconfig to prevent the configuration file from being loading on startup

  • New command line option --config-file to show the full path to the configuration file

  • New command disconnect to disconnect from a Tomcat server

  • New method TomcatManager.disconnect()

Changed
  • Output from the settings command now matches the TOML format of the configuration file

  • settings command now accepts input using TOML syntax

  • Server shortcuts have been renamed to server definitions. There is no change to the functionality, only a change to the name.

Removed
  • Drop support for Python 3.7 (EOL 27 June 2023)

  • Removed allow_style setting

  • Removed show command; settings does the same thing and is still available

Fixed
  • config edit command now sets default values before reloading configuration

6.0.1 (2022-11-15)

Added
  • Documentation for migrating to 6.x

Changed

6.0.0 (2022-11-14)

Added
  • Support for Python 3.11

  • Support for Tomcat 10.1

Changed
  • Change configuration file from ini format to toml format. See Configuration File for more information.

  • config_file attribute now contains a pathlib.Path object instead of a str for better cross-platform compatability

  • history_file attribute now contains a pathlib.Path object instead of a str for better cross-platform compatability

  • Switch to pyproject.toml from setup.py. This has no impact on functionality, it’s just a packaging change.

Removed
  • Support for Tomcat 8.0 (EOL 30 June 2018)

5.0.0 (2021-11-19)

Added
  • Support for Python 3.10

  • Cross-reference links to Requests and standard library documentation

Removed
  • Support for Python 3.6, which will not receive security fixes after 2021-12-23. Python 3.6 should still work for now, but we no longer test against it.

Fixed
  • TomcatManager.is_connected() now returns True or False instead of truthy or falsy values

  • Fix interactive py and pyscript commands which were broken by upstream changes in cmd2 version 2.0

4.0.0 (2021-08-26)

Added
  • Add py.typed file to make type annotations work properly per PEP 516

  • Add documentation showing how to specify tomcatmanager as a dependency in your package

Removed
  • Support for Tomcat 7, which is no longer supported or available for download

Fixed
  • Fixed bug when parsing authentication credentials on the shell command line to tomcat-manager

3.0.0 (2021-05-04)

Added
Changed
Fixed
  • TomcatManager.connect() no longer erroneously sets the url and user attributes if an exception is raised.

  • Allow --timeout=0 from the command line if you want to wait forever for network operations.

2.0.0 (2021-03-26)

Added
  • Support for Python 3.9

  • Support for Tomcat 10

  • New methods on TomcatManager: ssl_connector_certs(), ssl_connector_trusted_certs(), and ssl_reload()

  • New commands in tomcat-manager: sslconnectorcerts, sslconnectortrustedcerts and sslreload

  • Documentation for migrating from 1.x to 2.x

Changed
  • TomcatApplication.state now contains an Enum instead of an AttrDict

  • The tomcatmanager.application_states dict has been replaced by the tomcatmanager.ApplicationState enum

  • Timeouts can now be float instead of int

  • Improved documentation for network timeouts

Removed
  • Support for Python 3.5, which as of 2020-09-13 no longer receives security updates

  • Dependency on attrdict module, which has been archived

1.0.2 (2020-03-05)

Changed
  • upstream cmd2 library released v1.0.0. Now require cmd2>=1,<2.

Fixed
  • timeout command line and setting was not being honored

1.0.1 (2020-02-21)

Changed
  • cmd2=0.10 changed the way settings work. We now require that version or higher.

1.0.0 (2020-02-01)

Changed
  • Switch documentation theme from alabaster to sphinx_rtd_theme

Added
  • Already have a setting to control network timeouts. Added a command line option --timeout to do the same, making it easier for modify for command-line only use.

  • Adjustments for upstream changes in cmd2. No longer pinned to cmd2=0.9.4, but require cmd2>=0.9.14.

  • Add support for Python 3.8.

  • Add documentation style checking using doc8.

Removed
  • Drop support for Python 3.4, which reached end-of-life on Mar 18, 2019.

0.14.0 (2019-05-16)

Changed
  • invoke clean.pycache is now invoke clean.bytecode

  • Run tests using python 3.7 on Appveyor and Travis

  • Source code has been moved inside of src directory

  • Pin cmd2 to version 0.9.4; newer versions break us badly

0.13.0 (2018-07-06)

Added
  • In the interactive tomcat-manager tool, the history of previously executed commands is now persistent across invocations of the program.

  • Added common developer tasks to tasks.py. To run these tasks, use the invoke command provided by pyinvoke.

  • Tomcat 9.0.x officially supported. No material changes were required to gain this support, just validation via the test suite.

  • Type hinting added for enhanced developer productivity in most IDE’s

  • Full support for Python 3.7

Changed
  • ServerInfo.__init__() no longer accepts the result as a positional argument: it must be a keyword argument.

Fixed
  • Test suite now runs several orders of magnitude faster. The upstream cmd2 used pyparsing which was very slow. cmd2 versions >= 0.9.0 use shlex to parse commands.

0.12.0 (2018-02-23)

Added
  • You can now deploy applications via a context xml file. A new interactive command deploy context and a new method deploy_servercontext() provide this capability.

Changed
  • Better help messages in the interactive tomcat-manager tool

  • deploy() has been replaced by three new methods: deploy_localwar(), deploy_serverwar(), and deploy_servercontext().

  • Commands which use an optional version parameter now use a -v option to specify the version

  • Most commands now have -h/--help options

0.11.0 (2017-09-06)

Added
  • New command line switches for tomcat-manager: --quiet, --echo, --status_to_stdout

  • New setting status_prefix contains the string to emit prior to all status messages

  • New class TomcatApplication

Changed
  • If we get an http redirect during TomcatManager.connect(), save the new url so we don’t have to re-traverse the redirect on every command.

  • Interactive list command now can filter by application state, and has two sort options.

  • TomcatManager._user is now TomcatManager.user

  • TomcatManager._url is now TomcatManager.url

  • TomcatManager.list() now returns a list of TomcatApplication objects

  • Renamed tm.codes to tm.status_codes to clarify the purpose

0.10.0 (2017-08-24)

Added
  • CHANGELOG.rst

  • documentation for interactive mode

  • documentation for use from the shell command line

  • read settings from a config file

  • add config command which allows user to edit config file

  • server shortcuts: save url, user, and password in config file

  • which command to show which tomcat server you are connected to

  • timeout setting for HTTP timeouts

  • restart command as synonym for reload

  • Add tox for testing against multiple versions of python

Changed
  • status command now pretty prints the xml response

  • TomcatManager.__init__ no long accepts paramemeters: use connect instead

  • TomcatManager methods which act on apps (deploy, sessions,

    stop, etc.) now throw exceptions if no path is specified. Previously they returned a response with r.ok == False

0.9.2 (2017-08-16)

Added
  • new TomcatManager.connect() method

  • lots more documentation

  • pytest now runs doctests

Changed
  • version numbers now provided by setuptools_scm

0.9.1 (2017-08-10)

Changed
  • New release to practice packaging and distribution

0.9.0 (2017-08-10)

Added
  • Converted from a single script to an installable python package

  • Remove documentation for tomcat 6, which is no longer supported

  • Add expire command

  • Add vminfo command

  • Add sslconnectorciphers command

  • Add threaddump command

  • Add findleaks command

  • Add status command

  • Unit tests using pytest

  • Support Tomcat parallel deployment

  • Real documentation using Sphinx

  • Packaged to PyPI

Changed
  • Switch from getopt to argparse

  • Use cmd2, if available, instead of cmd

  • Switch from urllib to requests

Removed
  • Drop support for Python 3.3

Changes in 2014 and 2015

  • Remove methods deprecated in Python 3.4

  • Add documentation to support Tomcat 7

0.4 (2013-07-07)

Added
Removed
  • Drop support for python 2

0.3 (2013-01-02)

Added
  • Add code from private repo