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 theContext
element is ignored by the Tomcat Server when deploying from a context file.If the
Context
element specifies adocBase
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. IfFalse
, 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 optionTOMCATMANAGER_THEME
environment variablethe
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 |
---|---|
|
CSS-style hex notation |
|
RGB form using three integers |
|
color names |
|
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 or heavy text |
|
italic text (not supported on Windows) |
|
text with a strikethrough line |
|
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 succesfully1 = command had an error2 = incorrect usage127 = 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 |
---|---|---|
|
|
Add the command to the output stream. |
|
|
Don’t show non-essential feedback. |
|
|
Send status information to |
|
|
Show detailed exception and stack
trace, even if |
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 additionalserver_info
attribute
The
server_info
attribute of the returned object contains aServerInfo
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 theconnect()
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 theconnect()
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 callconnect()
,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 settingverify
toFalse
.See Authentication for more details.
Side Effects
Passing a
timeout
parameter to this method has the side effect of setting thetimeout
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 thecert
attribute.Upon successful connection, an instance of
TomcatMajorMinor
will be stored intomcat_major_minor
indicating the major version of Tomcat running on the server. Further details about the server are available in theserver_info
attribute of the returned response.Changed in version 3.0.0:
Returned
TomcatManagerResponse
now includes aserver_info
attribute containing aServerInfo
object describing the server we are connected toSets
tomcat_major_minor
attributetimeout
is now a keyword only argument
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 anOK
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 therequests.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:
TomcatManager.list()
- return a list of all installed applicationsTomcatManager.deploy_localwar()
- deploy a warfile on the local filesystem to the Tomcat serverTomcatManager.deploy_serverwar()
- deploy a war file from the server filesystem to the Tomcat serverTomcatManager.deploy_servercontext()
- deploy an application defined by a context file from the server filesystem to the Tomcat serverTomcatManager.undeploy()
- undeploy an application in the Tomcat serverTomcatManager.start()
- start an application already deployed in the Tomcat serverTomcatManager.stop()
- stop an application already deployed in the Tomcat serverTomcatManager.reload()
- stop and start a tomcat applicationTomcatManager.sessions()
- get the age of the sessions for an application.TomcatManager.expire()
- expire idle sessions
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.
TomcatManager.find_leakers()
- find applications that are leaking memoryTomcatManager.resources()
- get global JNDI resourcesTomcatManager.server_info()
- get information about the tomcat serverTomcatManager.status_xml()
- get server status information in xml formatTomcatManager.thread_dump()
- get a jvm thread dumpTomcatManager.vm_info()
- get diagnostic information about the jvm
SSL/TLS
Tomcat servers can be configured to serve their applications over SSL/TLS. This library includes a few related methods:
TomcatManager.ssl_connector_ciphers()
- get SSL/TLS ciphers for eac connectorTomcatManager.ssl_connector_certs()
- get the certificate chain for each virtual hostTomcatManager.ssl_connector_trusted_certs()
- get the trusted certificates for each virtual hostTomcatManager.ssl_reload()
- reload certificates and keys
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.
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:
Seconds to wait before giving up on network operations.
Url of the Tomcat Manager web application we are connected to.
User we successfully authenticated to the Tomcat Manager web application with.
Client side SSL/TLS certificates we authenticated to the Tomcat Manager web application with.
The certificate authority directory or bundle to use to verify server SSL/TLS certificates.
If connected to a server, this contains an instance of
TomcatMajorMinor
describing the major version of Tomcat we are connected to.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 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.
Get information about the Tomcat server.
Get server status information in XML format.
vm_info
()Get diagnostic information about the JVM.
Get a JVM thread dump.
resources
([type_])Get the global JNDI resources
Get apps that leak memory.
Get SSL/TLS ciphers configured for each connector.
Get the SSL certificate chain currently configured for each virtual host
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 anint
. Default is10
. I surely don’t want to wait forever, but if you do, set to0
.Usage:
>>> import tomcatmanager as tm >>> tomcat = tm.TomcatManager() >>> tomcat.timeout = 3.5
Changed in version 3.0.0: Can be a
float
orint
instead of just anint
- 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 checktomcat_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 additionalserver_info
attribute
The
server_info
attribute of the returned object contains aServerInfo
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 theconnect()
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 theconnect()
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 callconnect()
,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 settingverify
toFalse
.See Authentication for more details.
Side Effects
Passing a
timeout
parameter to this method has the side effect of setting thetimeout
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 thecert
attribute.Upon successful connection, an instance of
TomcatMajorMinor
will be stored intomcat_major_minor
indicating the major version of Tomcat running on the server. Further details about the server are available in theserver_info
attribute of the returned response.Changed in version 3.0.0:
Returned
TomcatManagerResponse
now includes aserver_info
attribute containing aServerInfo
object describing the server we are connected toSets
tomcat_major_minor
attributetimeout
is now a keyword only argument
- 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 theresult
attribute and thesessions
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 theresult
attribute and thesessions
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 additionalapps
attribute which contains a list ofTomcatApplication
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 additionalserver_info
attribute
The
server_info
attribute contains aServerInfo
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 additionalstatus_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 additionalvm_info
attribute
- thread_dump() TomcatManagerResponse
Get a JVM thread dump.
- Returns:
TomcatManagerResponse
object with an additionalthread_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 additionalresources
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 additionalleakers
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 additionalssl_connector_ciphers
attribute
- ssl_connector_certs() TomcatManagerResponse
Get the SSL certificate chain currently configured for each virtual host
- Returns:
TomcatManagerResponse
object with an additionalssl_connector_certs
attribute
- ssl_connector_trusted_certs() TomcatManagerResponse
Get the trusted certificates currently configured for each virtual host
- Returns:
TomcatManagerResponse
object with an additionalssl_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 anOK
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 therequests.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:
- 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 customLookupDict
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:
- 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
- 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 theconnect()
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:
TomcatManager.user
is now a read-only property instead of a read-write attribute, useTomcatManager.connect()
to set this value.TomcatManager.url
is now a read-only property instead of a read-write attribute, useTomcatManager.connect()
to set this valueif you call a method on
TomcatManager
which requires network interaction with the Tomcat server (which is all the methods that do anything interesting) and you haven’t calledTomcatManager.connect()
first,TomcatNotConnected
will be raised. In tomcatmanager 2.x, you will either connect successfully if you had setTomcatManager.url
properly, or you would get some sort of HTTP error.since we were already making a breaking change to
TomcatManager.connect()
, I decided to make another: thetimeout
parameter used to be positional, now it is keyword only. If you were passing it as positional, your calls toTomcatManager.connect()
will now break, and you’ll have to fix them. If you were specifying the timeout by setting theTomcatManager.timeout
attribute, that continues to work as before.
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 |
---|---|---|
|
3.12.0 |
tomcatmanager-3.12 |
|
3.12.0 |
tomcatmanager-3.12 |
|
3.12.0 |
tomcatmanager-3.12 |
|
3.11.5 |
tomcatmanager-3.11 |
|
3.10.13 |
tomcatmanager-3.10 |
|
3.9.18 |
tomcatmanager-3.9 |
|
3.8.18 |
tomcatmanager-3.8 |
|
3.11.5 |
tomcatmanager-3.11 |
|
3.11.5 |
tomcatmanager-3.11 |
|
3.11.5 |
tomcatmanager-3.11 |
|
3.10.13 |
tomcatmanager-3.10 |
|
3.9.18 |
tomcatmanager-3.9 |
|
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]
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
rolethe 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:
Merge everything to be included in the release into the develop branch.
Run
tox
to make sure the tests pass in all the supported python versions.Review and update
CHANGELOG.rst
.Update and close the milestone corresponding to the release at https://github.com/tomcatmanager/tomcatmanager/milestones
Push the develop branch to github.
Tag the develop branch with the new version number and push the tag
Create a pull request on github to merge the develop branch into main. Wait for the checks to pass.
Merge the develop branch into the main branch and close the pull request.
Create a new release on Github summarizing the changelog
Change to the main branch.
Install the released version by
pip install -e .[dev]
Build source distribution, wheel distribution, and upload them to testpypi:
$ invoke testpypi
Build source distribution, wheel distribution, and upload them to pypi:
$ invoke pypi
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.
Switch back to the develop branch.
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 outputNew
theme
setting to choose which theme to useNew command line option
--theme
to set theme from command lineNew environment variable
TOMCATMANAGER_THEME
to set theme from environmentNew
theme
command for users to list, create, edit, and delete themesTheme 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
, anddefault-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 startupNew command line option
--config-file
to show the full path to the configuration fileNew command
disconnect
to disconnect from a Tomcat serverNew method TomcatManager.disconnect()
Changed
Output from the
settings
command now matches the TOML format of the configuration filesettings
command now accepts input using TOML syntaxServer 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
Improved documentation for module dependency specification
Improved documentation for differences in Tomcat versions
6.0.0 (2022-11-14)
Added
Support for Python 3.11
Support for Tomcat 10.1
Changed
Change configuration file from
ini
format totoml
format. See Configuration File for more information.config_file
attribute now contains apathlib.Path
object instead of astr
for better cross-platform compatabilityhistory_file
attribute now contains apathlib.Path
object instead of astr
for better cross-platform compatabilitySwitch to
pyproject.toml
fromsetup.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
orFalse
instead of truthy or falsy valuesFix interactive
py
andpyscript
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 516Add 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
Support for discovering and exposing the version of the Tomcat server we are connected to in the API. See TomcatManager.connect(), TomcatManager.implements(), and TomcatManager.implemented_by().
TomcatMajorMinor enumeration for supported versions of Tomcat. Major and minor have the meaning defined at https://semver.org/.
TomcatManager.tomcat_major_minor attribute which contains one of the values from TomcatMajorMinor representing the version of the Tomcat server we are connected to.
Control server SSL/TLS certificate validation using the new
verify
parameter to TomcatManager.connect(). Also available from the command-line and interactive mode using the--cacert
and--noverify
options of theconnect
command.Client side SSL/TLS certificate authentication added to TomcatManager.connect() via the
cert
parameter. Also available from the command line and interactive mode using the--cert
and--key
options of theconnect
command.Documentation explaining all authentication approaches with configuration and usage examples.
Documentation for migrating from 2.x to 3.x.
Changed
TomcatManager methods raise TomcatNotConnected if called before connect(). Previously you got a TomcatManagerResponse and had to call raise_for_status() or check ok in order to determine that you weren’t connected.
TomcatManager.url and TomcatManager.user are now read-only properties set by TomcatManager.connect().
TomcatManager methods raise TomcatNotImplementedError if the server does not implement the requested capability. For example ssl_reload() is not implemented by Tomcat 7.0.x or 8.0.x, so if you are connected to a Tomcat 7.0.x server and call ssl_reload(), TomcatNotImplementedError will be raised.
Timeouts were previously
int
only, now they can befloat
The
timeout
parameter to TomcatManager.connect() is now keyword only.
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()
, andssl_reload()
New commands in
tomcat-manager
:sslconnectorcerts
,sslconnectortrustedcerts
andsslreload
Documentation for migrating from 1.x to 2.x
Changed
TomcatApplication.state
now contains anEnum
instead of anAttrDict
The
tomcatmanager.application_states
dict has been replaced by thetomcatmanager.ApplicationState
enumTimeouts can now be
float
instead ofint
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 requirecmd2>=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
tosphinx_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 tocmd2=0.9.4
, but requirecmd2>=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 nowinvoke clean.bytecode
Run tests using python 3.7 on Appveyor and Travis
Source code has been moved inside of
src
directoryPin 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 theinvoke
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
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 methoddeploy_servercontext()
provide this capability.
Changed
Better help messages in the interactive
tomcat-manager
tooldeploy()
has been replaced by three new methods:deploy_localwar()
,deploy_serverwar()
, anddeploy_servercontext()
.Commands which use an optional version parameter now use a
-v
option to specify the versionMost 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 messagesNew 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 nowTomcatManager.user
TomcatManager._url
is nowTomcatManager.url
TomcatManager.list()
now returns a list ofTomcatApplication
objectsRenamed
tm.codes
totm.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 fileserver shortcuts: save url, user, and password in config file
which
command to show which tomcat server you are connected totimeout
setting for HTTP timeoutsrestart
command as synonym forreload
Add tox for testing against multiple versions of python
Changed
status
command now pretty prints the xml responseTomcatManager.__init__
no long accepts paramemeters: useconnect
insteadTomcatManager
methods which act on apps (deploy
,sessions
,stop
, etc.) now throw exceptions if no path is specified. Previously they returned a response withr.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
commandAdd
vminfo
commandAdd
sslconnectorciphers
commandAdd
threaddump
commandAdd
findleaks
commandAdd
status
commandUnit 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 ofcmd
Switch from
urllib
torequests
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
Port to python 3
New
resources
command
Removed
Drop support for python 2
0.3 (2013-01-02)
Added
Add code from private repo