If you’re used to automating WildFly configuration with its CLI, you’ve probably faced the need for passing parameters to your scripts. In the era of Docker, which is a common way to distribute and run WildFly, things are usually passed around through environment variables. In this post, we’ll show how to get environment variables into CLI scripts.

By default, the CLI doesn’t have access to environment variables. However, you can give it a .properties file containing key-value pairs for substitution. Using env or printenv commands, we can easily generate a file containing our environment variables:

$ printenv > $JBOSS_HOME/env.properties

We can then supply the file to the CLI via --properties:

$ $JBOSS_HOME/bin/jboss-cli.sh --file=myscript.cli --properties=env.properties

This is a common construct I use in my Docker setup – the Dockerfiles for configuring the application server start with several ENV instructions, followed by a RUN instruction with the command creating a file from the output of printenv. Further in the Dockerfile, another RUN instruction calls the CLI with the generated file.

This allows us to use environment variables in a script – just enclose the variable name in curly braces with a dollar sign (${}).

Let’s demonstrate this on an example. Suppose we want to create a system property. The name of the property is defined in a PROPERTY_NAME environment variable. The value is set to a fixed string – bar. We can accomplish this with the following script, let’s call it property-setter.cli:

/system-property=${PROPERTY_NAME}:add(value="bar")

From $JBOSS_HOME, we’ll call the script as follows:

$ export PROPERTY_NAME=foo
$ printenv > env.properties
$ ./bin/jboss-cli.sh -c --file=property-setter.cli --properties=env.properties
{"outcome" => "success"}

The operation succeeded. The output in standalone.xml looks as follows:

<system-properties>
    <property name="foo" value="bar"/>
</system-properties>

Now let’s imagine a slightly different, more useful scenario. Instead of using an environment variable to determine the name of the property with a fixed value, let’s create a system property called foo, whose value is set to the value of the PROPERTY_VALUE environment variable.

We’ll update our CLI script to look as follows:

/system-property=foo:add(value="${PROPERTY_VALUE}")

We’ll call the script:

$ export PROPERTY_VALUE=bar
$ printenv > env.properties
$ ./bin/jboss-cli.sh -c --file=property-setter.cli --properties=env.properties
{
    "outcome" => "failed",
    "failure-description" => "WFLYCTL0211: Cannot resolve expression '${PROPERTY_VALUE}'",
    "rolled-back" => true
}

As we can see, the operation did not succeed. This is due to the fact that the CLI does not treat values the same as names. In short, operation names, parameter names, header names and values, command names as well as command argument names are resolved automatically. Parameter and argument values aren’t. To fix this, we need to set resolve-parameter-values to true in jboss-cli.xml. For example:

$ sed -i "s/<resolve-parameter-values>false<\/resolve-parameter-values>/\
<resolve-parameter-values>true<\/resolve-parameter-values>/" \
$JBOSS_HOME/bin/jboss-cli.xml

Note that the command above is meant to be a one-off solution. From maintenance perspective, using sed for XML is not a good idea in general. If you’re automating this, consider using XPath instead.

Now that we’ve updated the configuration, the operation in the CLI script succeeds:

$ ./bin/jboss-cli.sh -c --file=property-setter.cli --properties=env.properties
{"outcome" => "success"}

The relevant section of standalone.xml looks as expected:

<system-properties>
    <property name="foo" value="bar"/>
</system-properties>

Note that this functionality requires WildFly 8.0.0.CR1 or newer.

To sum up: