21.2. Setting up the Drift Definition and Preparing the Bundle

The setup script actually runs through three CLI scripts and some system commands. Having all of the steps in a single script makes it possible to set up a drift definition and a backup bundle by running a single command:
[root@server ~]# ./driftBundle.sh
Both drift definitions and bundle deployments take a lot of resource- and infrastructure-specific settings. The driftBundle.sh script in this example defines a lot of variables in the script to account for each piece of information.
The variables could be defined using a .conf or even a set of .conf files (cf. Section 18.2, “Creating the Wrapper Script and .conf File”), but for simplicity in this example, all of the variables are defined in the driftBundle.sh script itself.
The first part of the script simply defines the connection settings to use when running the JBoss ON CLI. This example only defines a username and password, so it assumes that the script is run on a system which also has a JBoss ON server running locally. The options could be edited to supply a remote JBoss ON server hostname and port.
There are three general variables defined:
  • The location of the rhq-cli.sh script
  • Any options, such as the username and password, to pass with the CLI command
  • The directory to use both to save the generated JavaScript files and to use for the path to JavaScript files
# options for the CLI
OPTS=' -u rhqadmin -p rhqadmin'
The first part of the script sets up the drift definition. By default, drift is only enabled for a handful of resource types — JBoss servers, Tomcat servers, and platforms — so it is easiest to identify the resource based on a combination of its resource type and name.
Once the resource is identified, then the definition can be created. A general definition will identify the base directory to monitor, set some rules about what files or subdirectories to ignore (like log files), and set an interval or frequency for drift detection scans.
All of these definition parameters are defined as individual variables in the shell script. In this example, drift is configured for a platform.
# set parameters for the drift definition
NAME='example drift'
DESC='drift from script'
The shell script will eventually create a CLI script that is run automatically in the CLI. The first part of the CLI script defines a resource type criteria search for the platform, and then the resource platform itself.
driftDef() {
cat <<-EOF

//set the resource type
var resType = ResourceTypeManager.getResourceTypeByNameAndPlugin("$RESTYPE","$RESPLUGIN");

//get the resource to associate with the drift definition
rcrit = ResourceCriteria()
var resources = ResourceManager.findResourcesByCriteria(rcrit)
var res = resources.get(0)
This script searches for a single resource to configure for drift. You could also create the script to search for multiple resource and add them to a compatible group, and the iterate through the compatible group to add the drift definition to each resource.
The next part configures the drift definition itself. The DriftDefinitionManager is a wrapper for a Configuration() object. The CLI script first calls for the default drift template for the given resource type and then creates a definition object based on that template.
//get the default template for the resource type
criteria = DriftDefinitionTemplateCriteria()
templates = DriftTemplateManager.findTemplatesByCriteria(criteria)
template = templates.get(0)
//create a new drift definition instance, based on the template
definition = template.createDefinition()
Once the configuration object is created, then the definition options are assigned values.
This script creates a real drift definition with one exception: it sets a very low scan interval, 30 seconds. In fact, that is the shortest configurable interval. This allows the agent to collect the initial snapshot fairly quickly, which helps the overall setup go faster. This interval will be reset to a more reasonable value (the one defined in the variables) at the end of the script execution.
//set the drift definition configuration options
definition.resource = res
definition.name = '$NAME'
definition.description = '$DESC'
definition.setAttached(false) // this is false so that template changes don't affect the definition
// this is set low to trigger an early initial detection run
var basedir = new DriftDefinition.BaseDirectory(DriftConfigurationDefinition.BaseDirValueContext.valueOf('$BASEDIRTYPE'),'$BASEDIR')
definition.basedir = basedir

// there can be multiple exclude statements made, as desired
var f = new Filter("$EXCLUDE", "$PATTERN") // location, pattern

//this defaults to normal, which means that any changes will
// trigger an alert. plannedChanges is the other option, which 
// disables alerting for drift changes.
Once the configuration is complete, it needs to be written to the definition.
//apply the new definition to the resource

The drift definition uses an entity context rather than the resource ID alone to identify the resource. An entity context first identifies the type of object (the entity) and then its associated inventory ID.
There are actually several different steps for creating a "bundle" because there is no one part to a "bundle." The script makes a ZIP archive of the given drift base directory, and that makes the bundle archive. Then, for defining the bundle, there are two steps. There is defining the bundle destination, which is a compatible group to which bundles (any bundles) can be deployed plus the location on the resources for deploying the bundles. Then the package itself is uploaded as a bundle version.
The variables define both the information for the bundle version and bundle archive and for the bundle destination.
There is one other variable included: the path to the CLI's samples directory. Helper functions to create bundle versions, to create bundle destinations, and to deploy specified bundles are already defined in the bundles.js sample script. Using those functions makes deploying bundles very easy.
# options for the bundle
DESTNAME='drift destination'
BUNDLEDESC='bundle to remediate drift'
GROUPNAME='Linux Group'
This particular bundle deployment is pretty simple. The target bundle destination is the same as the drift base directory.
Since there are no tokens to realize or external content to pull in, just the backup archive itself, the recipe can be pretty simple. This script creates the recipe (deploy.xml) which is used in the bundle archive.
deploy() {
cat << _EOF_

<project name="$BUNDLENAME" default="main"
    <rhq:bundle name="$BUNDLENAME" version="$BVER" description="$BUNDLEDESC">
        <rhq:deployment-unit name="drift" compliance="full">
            <rhq:archive name="$ZIP" exploded="true">
<target name="main" />

The bundles.js sample script already defines all of the functions required to deploy bundles, but it relies on the util.js sample script. When the CLI is run non-interactively, there is no way to import an external script that another script requires.
So, this shell script first concatenates the bundles.js and util.js scripts together, and then appends the calls to create the bundle version and the bundle destination.
createBundle() {
cat $SAMPLES/util.js $SAMPLES/bundles.js
cat  << _EOF_

// set the location of the bundle archive
var path = '$BUNDLE'

// create the bundle version in JON

// set all of the variables for the bundle destination
var destinationName = '$DESTNAME'
var description = '$BUNDLEDESC'
var bundleName = '$BUNDLENAME'
var groupName = '$GROUPNAME'
var baseDirName = '$BASEDIR'
var deployDir = "."

// create the new destinition in JON
createBundleDestination(destinationName, description, bundleName, groupName, baseDirName, deployDir)

Make sure that the resource already belongs to a compatible group and that the compatible group has a unique enough name so that it is the only one returned in the search.
The last CLI script created by the shell script pins the initial snapshot to the new drift definition. A snapshot, as the name implies, is a picture of the current settings of the base directory. Pinning a snapshot to a definition sets a baseline, or comparison, for the agent to use to evaluate drift. A pinned snapshot is a specific and identified configuration that must be maintained (as opposed to rolling changes).
Once the snapshot is pinned, this script then resets the drift definition configuration so that it uses a longer (more realistic) interval between scans.
snapshot() {
cat <<- _EOF_
//find the resource
rcrit = ResourceCriteria()
var resources = ResourceManager.findResourcesByCriteria(rcrit)
var res = resources.get(0)

//find the new drift definition
criteria = DriftDefinitionCriteria()
def = DriftManager.findDriftDefinitionsByCriteria(criteria)
definition = def.get(0)

// it is necessary to redefine the complete configuration when you're 
// resetting the interval or the other values will be overwritten with default 
// or set to null
var basedir = new DriftDefinition.BaseDirectory(DriftConfigurationDefinition.BaseDirValueContext.valueOf('$BASEDIRTYPE'),'$BASEDIR')
definition.basedir = basedir
definition.name = '$NAME'
// there can be multiple exclude statements made, as desired
var f = new Filter("$EXCLUDE", "$PATTERN") // location, pattern

// pin to the initial snapshot, which is version 0
// this gets the most recent snapshot if that is the better version to use
// snap = DriftManager.getSnapshot(DriftSnapshotRequest(definition.id))
The last part of the script actually runs all of the defined JBoss ON CLI scripts and sets up both the drift definition and the bundle definition (as a backup in case any drift is detected).
There are two system commands sandwiched between the JBoss ON CLI scripts. The first is the zip commands to create the bundle archive. The second is a sleep command which pauses the script to give the JBoss ON agent time to collect the initial snapshot for drift before attempting to pin the snapshot.
# create the drift definition

driftDef > $SCRIPTS/driftDef.js
$CLI $OPTS -f $SCRIPTS/driftDef.js

# create the recipe file and then zip up the 
# drift base directory to make the bundle archive

deploy > /deploy.xml
zip $BUNDLE $ARCHIVE /deploy.xml

# create the bundle from the recipe and archive
# and then create the bundle definition 

createBundle > $SCRIPTS/createBundle.js
$CLI $OPTS -f $SCRIPTS/createBundle.js

# sleep to allow the server to get the first snapshot
# this only sleeps for a minute, but it really depends on your environment
# whether that is long enough

sleep 1m

# this pins the new snapshot to the new drift definition
# and then changes the drift interval to the longer, variable-specified
# value

snapshot > $SCRIPTS/snapshot.js
$CLI $OPTS -f $SCRIPTS/snapshot.js
There is no error handling in this shell script. If any step fails, like the initial snapshot taking longer than the sleep period, there is no indication of what went wrong aside from malformed drift or bundle configuration.