Skip to main content

Programmable Configuration

You can write simple Velocity scripts to automatically configure your monitoring resources by pulling data from an HTTP portal (like NetBox), reading local files, SQL databases, running local commands, or parsing JSON content. Templates can also be re-evaluated on a schedule to keep the configuration in sync with these sources.

This is ideal for:

  • Large environments with hundreds or thousands of resources
  • Dynamic infrastructures where resources are frequently added or removed
  • Integration with CMDBs or inventory systems

The following Velocity Tools are supported to fetch and transform data into valid configuration blocks:

ToolPurpose
$httpMaking HTTP requests to APIs
$fileReading local files
$jsonParsing JSON data
$collectionSplitting strings or manipulating collections
$sqlExecuting SQL queries on a database
$commandExecuting local commands and scripts
$envRetrieving environment variables
$scheduleScheduling the re-evaluation of the template
$date, $number, $escDate formatting, number formatting, escaping

Writing Velocity Templates​

  1. Connect to the Web Interface at https://MACHINE_WHERE_METRICSHUB_IS_RUNNING:31888
  2. Click Tools > YAML Editor, then Create > New Velocity template
  3. In the editor, write your Velocity script to either load resources from:
  1. Click Test to validate your script and preview the generated configuration blocks
  2. Click Save
  3. When ready, click Apply.
note

In Velocity, use # for directives, ## for comments, and $ for variables.

Loading Resources​

From an HTTP API​

Use the $http.execute(...) function to execute HTTP requests directly from templates.

$http.execute Tool Arguments​

ArgumentDescription
url(Required) The HTTP(S) endpoint to call.
methodHTTP method (GET, POST, etc.). (Default: GET). Use $http.get(...) or $http.post(...) to quickly send GET or POST requests without specifying a method
usernameUsername used for authentication.
passwordPassword used for authentication.
headersHTTP headers, written as newline-separated Key: Value pairs.
bodyPayload to send with the request (e.g., for POST).
timeoutRequest timeout in seconds. (Default: 60).

Example​

Suppose your API endpoint at https://cmdb/servers returns:

[
{ "hostname": "host1", "OSType": "win", "adminUsername": "admin1" },
{ "hostname": "host2", "OSType": "win", "adminUsername": "admin2" }
]

You can dynamically create resource blocks using:


resources:
#set($hostList = $json.parse($http.get({ "url": "https://cmdb/servers" }).body).root())

#foreach($host in $hostList)
#if($host.OSType == "win")
$host.hostname:
attributes:
host.name: $host.hostname
host.type: windows
protocols:
ping:
wmi:
timeout: 120
username: $host.adminUsername
password: $http.get({ "url": "https://passwords/servers/${host.hostname}/password" }).body
#end
#end

From a Local File​

Use the $file.readAllLines(filePath) function to read all lines from a local file.

$file.readAllLines Tool Arguments​

ArgumentDescription
filePath(Required) The path to the local file.

Example​

If your CSV file contains:

host1,win,wmi,user1,pass1
host2,linux,ssh,user2,pass2

Use this Velocity template to generate the resource block:


#set($lines = $file.readAllLines("/opt/data/resources.csv"))
resources:
#foreach($line in $lines)
#set($fields = $collection.split($line))
#set($hostname = $fields.get(0))
#set($hostType = $fields.get(1))
#set($protocol = $fields.get(2))
#set($username = $fields.get(3))
#set($password = $fields.get(4))
$hostname:
attributes:
host.name: $hostname
host.type: $hostType
protocols:
$protocol:
username: $username
password: $password
#end

From an SQL Database​

Use the $sql.query(query, jdbcUrl, username, password, timeout) function to execute SQL queries.

$sql.query Tool Arguments​

ArgumentDescription
query(Required) SQL query to execute.
jdbcUrl(Required) The JDBC connection URL to access the database.
usernameName used for database authentication.
passwordPassword used for database authentication.
timeout(Optional) Query timeout in seconds (Default: 120).

Example​

Consider a hosts table in your database with the following data:

hostnamehost_typeusernamepassword
storage-server-1storageadmin1pwd1
windows-server-1windowsadmin2pwd2

You can dynamically create resource blocks by querying the database:


#set($url = "jdbc:h2:mem:management_db")
#set($user = "sa")
#set($pass = "pwd1")
#set($rows = $sql.query("SELECT hostname, host_type, username, password FROM hosts ORDER BY hostname", $url, $user, $pass, 120))
resources:
#foreach($row in $rows)
#set($hostname = $row.get(0))
#set($host_type = $row.get(1))
#set($username = $row.get(2))
#set($password = $row.get(3))
#if($host_type.equals("storage"))
$hostname:
attributes:
host.name: $hostname
host.type: $host_type
protocols:
http:
hostname: $hostname
https: true
port: 443
username: $username
password: $password
#end
#end

From a Command Line​

Use the $command.execute(...) function to run a local command or script (a discovery script, a cloud CLI such as aws, az or kubectl, an inventory tool, etc.) and build your resources from its output.

The command is executed through the system shell (cmd.exe /C on Windows, $SHELL -c or /bin/sh -c on Linux/UNIX), so pipes, redirections and && are supported.

You can call it either with the command line only:

#set($result = $command.execute("/opt/scripts/list-hosts.sh"))

or with a map of arguments:

#set($result = $command.execute({
"command": "/opt/scripts/list-hosts.sh",
"timeout": "30",
"workingDirectory": "/opt/scripts",
"failOnError": "true"
}))

$command.execute Tool Arguments​

ArgumentDescription
command(Required) The command line to execute.
timeoutExecution timeout in seconds. The command and its child processes are killed when the timeout is reached. (Default: 60).
workingDirectoryDirectory from which the command is executed. (Default: the working directory of MetricsHub).
charsetCharset used to decode the command output (e.g., UTF-8, ISO-8859-1, Cp850). (Default: UTF-8).
envAdditional environment variables, written as newline-separated KEY=VALUE pairs. They are added to the environment inherited from MetricsHub.
failOnErrorSet to true to make the template fail when the command exits with a non-zero code. The error is then reported in the Web Interface. (Default: false).

Result​

$command.execute(...) returns an object with the following properties:

PropertyDescription
stdoutThe standard output of the command.
stderrThe standard error output of the command.
exitCodeThe exit code of the command (0 = success).

When failOnError is false (default), a command exiting with a non-zero code does not stop the template: a warning is logged, and you can check $result.exitCode to handle the failure in your template.

Example​

Suppose the /opt/scripts/list-hosts.sh script returns one hostname per line:

host1
host2

You can dynamically create resource blocks using:


#set($result = $command.execute({ "command": "/opt/scripts/list-hosts.sh", "timeout": "30" }))
resources:
#if($result.exitCode == 0)
#foreach($line in $result.stdout.split("\n"))
#set($hostname = $line.trim())
#if(!$hostname.isEmpty())
$hostname:
attributes:
host.name: $hostname
host.type: linux
protocols:
ssh:
username: admin
password: $env.get("SSH_PASSWORD")
#end
#end
#end

If the command returns JSON, combine it with the $json tool:

#set($nodeList = $json.parse($command.execute("kubectl get nodes -o json").stdout).root())

To pass environment variables to the command, use the env argument. Like the headers argument of $http.execute, env is a string (not a map) containing one KEY=VALUE pair per line:

#set($result = $command.execute({
"command": "/opt/scripts/list-hosts.sh",
"env": "INVENTORY_URL=https://cmdb/api"
}))

To pass several variables, put each KEY=VALUE pair on its own line within the string (leading spaces are ignored, so you can indent the lines):

#set($result = $command.execute({
"command": "/opt/scripts/list-hosts.sh",
"env": "INVENTORY_URL=https://cmdb/api
INVENTORY_SITE=paris"
}))
warning

Commands are executed on the machine where MetricsHub is running, with the privileges of the account running MetricsHub. Only use commands and scripts you trust, and restrict write access to your Velocity templates accordingly.

Using Environment Variables​

Use $env.get("ENV_VARIABLE_NAME") to retrieve environment variables in your templates:

#set($apiKey = $env.get("CMDB_API_KEY"))
#set($response = $http.get({
"url": "https://cmdb/api/servers",
"headers": "Authorization: Bearer $apiKey"
}))

This allows you to keep sensitive credentials out of your template files.

Re-evaluating Templates on a Schedule​

By default, a Velocity template is evaluated only when MetricsHub starts and whenever the template file is modified. However, the data returned by $http, $sql, $file or $command may change while the template itself does not (e.g., a new host is added to your CMDB).

Use $schedule.cron(...) to have MetricsHub re-evaluate the template periodically:

## Re-evaluate this template every 15 minutes
$schedule.cron("0 */15 * * * *")

Each time the schedule fires, the whole template is evaluated again from scratch: every $http, $sql, $file and $command call is run again. If the generated configuration differs from the previous one, MetricsHub automatically reloads its configuration to apply the changes. If the result is unchanged, nothing is reloaded.

$schedule.cron Tool Arguments​

ArgumentDescription
cronExpression(Required) The cron expression that defines when the template is re-evaluated.

The cron expression is made of 6 fields: second minute hour day-of-month month day-of-week. The @hourly, @daily, @weekly, @monthly and @yearly macros are also accepted.

Cron expressionRe-evaluation
0 */5 * * * *Every 5 minutes
0 0 * * * *Every hour
0 0 6 * * *Every day at 6:00 AM
0 0 8 * * MON-FRIEvery weekday at 8:00 AM
@dailyEvery day at midnight
note
  • $schedule.cron(...) prints nothing in the generated configuration and can be placed anywhere in the template.
  • A template can only have one schedule. If $schedule.cron(...) is called several times, only the last expression is applied and a warning is logged.
  • An invalid cron expression is logged as an error and ignored. The other templates keep being re-evaluated normally.
  • Removing $schedule.cron(...) from a template stops its periodic re-evaluation. New or deleted templates are taken into account without restarting MetricsHub.

Example​

The template below queries the CMDB every hour and automatically adds or removes the corresponding resources:


$schedule.cron("0 0 * * * *")
resources:
#set($hostList = $json.parse($http.get({ "url": "https://cmdb/servers" }).body).root())
#foreach($host in $hostList)
$host.hostname:
attributes:
host.name: $host.hostname
host.type: $host.OSType
protocols:
ping:
#end

Re-evaluating a Template on Demand​

To re-evaluate a template immediately, without waiting for its schedule:

  1. Connect to the Web Interface
  2. Click Tools > YAML Editor and select the Velocity template (.vm)
  3. Click Reevaluate.

The template is evaluated again, and the running configuration is reloaded only if the result has changed.