Chapter 27. Deploying Content and Applications Through Bundles

27.1. An Introduction to Provisioning Content Bundles

Provisioning is a way that administrators can define and control applications, from development to production. The ultimate effect of the provisioning system is simplifying how applications are deployed. Administrators can control which versions of the same application are deployed to different resources, from different content sources, within the same application definition (the bundle definition). Resources can be reverted to different versions or jump ahead in deployment.
Provisioning takes one set of files (a bundle) and then pushes it to a platform or an application server (the destination). There are more complex ways of defining the content, the destinations, and the rules for that deployment, but the core of the way that provisioning handles content is to take versioned bundles and send it to the designated resource.
Provisioning works with compatible groups, not individual resources. Administrators can define groups based on disparate environments and consistently apply application changes (upgrades, new deployments, or reversions) across all group members, simultaneously.
And the type of content which can be deployed, itself, is flexible. A bundle can contain raw configuration files, scripts, ZIP archives, JAR files, or full application servers — the definition of content is fairly loose.
This is in contrast to the resource-level content management in JBoss ON. The type of content is relatively limited. Patches or configuration is applied per-resource. New applications can only be deployed as children of existing resources and it has to be another resource type.
Provisioning focuses on application management, not purely resource management.

27.1.1. Bundles: Content and Recipes

A bundle is a set of content, packaged in an archive. In real life, a bundle is usually an application, but it can also contain a set of configuration files, scripts, libraries, or any other content required to set up an application or a resource.
The purpose of a bundle is to take that defined set of content and allow JBoss ON to copy it onto a remote resource. The provisioning process basically builds the application on the targeted resource, so in that sense, the bundle is an application distribution. Each bundle version has its own recipe which tells JBoss ON what files exist in the bundle, any tokens which need to have real values supplied at deployment, and how to handle the bundle and existing files on the remote machine.
The recipe, configuration files, and content are all packaged together into the bundle. This is usually a ZIP file, which the agent unpacks during provisioning.
As with other content managed in JBoss ON, the bundle is versioned. Different versions can be deployed to different resources, which is good for handling different application streams in different environments (say, QA and production). Versioning bundles also allows JBoss ON to revert or upgrade bundles easily.
The bundle can contain almost any kind of content, but it has to follow a certain structure for it to be properly deployed by JBoss ON. The recipe is an Ant build file called deploy.xml; this must always be located in the top level of the bundle archive.
Past the placement of the recipe, the files and directories within the bundle can be located anywhere in the archive. In fact, the files do not necessarily need to be included in the bundle file at all; when the bundle is created, any or all files for the bundle can be pulled off a URL, which allows the content to be taken from an SVN or GIT repository, FTP server, or website.
Bundle Layout

Figure 27.1. Bundle Layout

The bundle archive can contain other archives, such as JAR, WAR, and ZIP files. Provisioning uses Ant to build out bundles on the target machine, so any files which Ant can process can be processed as part of the bundle. The Ant provisioning system can process WAR, JAR, and ZIP archive files.

27.1.2. Destinations (and Bundle Deployments)

Uploading a bundle to JBoss ON does not push the bundle anywhere, so it is not automatically associated with a resource or group. (Bundles, unlike content, is resource-independent. It exists as its own definition in JBoss ON, apart from the inventory.) When the bundle is actually provisioned, then the provisioning wizard prompts for the administrator to define the destination.
A destination is the place where bundles get deployed. The destination is the combination of three elements:
  • A compatible resource group (of either platforms or JBoss servers)
  • A base location, which is the root directory to use to deploy the bundle. Resource plug-ins define a base location for that specific resource type in the <bundle-target> element. This can be the root directory or, for JBoss servers, common directories like the profile directory. There may be multiple available base locations.
  • The deployment directory, which is a subdirectory beneath the base directory where the bundle content is actually sent.
For example, an administrator wants to deploy a web application to a JBoss EAP 5 server, in the deploy/myApp/ directory. The JBoss AS5 plug-in defines two possible base locations, one for the installation directory and one for the profile directory. The administrator chooses the profile directory, since the application is an exploded JAR file. The agent then derives the real, absolute path of the application from those three elements:
JBoss AS group + {$PROFILE_DIR} + deploy/myApp/
If the PROFILE_DIR is /opt/jbossas/default/server/, then the destination is:
/opt/jbossas/default/server/deploy/myApp/
If the same resource group contains a JBoss EAP instance running on a Windows server, with a PROFILE_DIR of C:\jbossas\server\, then the path is derived slightly differently, appropriate for the platform:
C:\jbossas\default\server\deploy\myApp
It is up to the agent, based on the platform and resource information for its inventory, to determine the absolute path for the destination to which the bundle should be deployed.
Once a bundle is actually deployed to a destination, then that association — bundle version and destination — is the bundle deployment.
Bundles, Versions, and Destinations

Figure 27.2. Bundles, Versions, and Destinations

27.1.3. File Handling During Provisioning

Behavior at Deployment

A bundle file contains a set of files and directories that should be pushed to a resource. However, the provisioning process does not merely copy the files over to the deployment directory. Provisioning treats a bundle as, essentially, a template that defines the entire content structure for the target (root) directory.

For example, a bundle contains these files:
app.conf
lib/myapp.jar
If the root directory is deploy/myApp/, then the final configuration is going to be:
deploy/myApp/app.conf
deploy/myApp/lib/myapp.jar
By default, if there are any files in deploy/myApp/, then they will be removed before the bundle is copied over, so that the deployment directory looks exactly the way the bundle is configured.
For an application-specific destination, like deploy/myApp/, then that behavior is totally acceptable because the defined application content should be the only content in that directory. However, bundles can contain a variety of content and can be deployed almost anywhere on a platform or within a JBoss server. In a lot of real life infrastructures, the directory where the bundle is deployed may have existing data that should be preserved.
The deployment directory is the root directory for the bundle. The recipe for the bundle can define a parameter that tells the provisioning process how to handle data in that root directory — specifically, should it ignore (preserve) existing files and subdirectories in the root directory, or should it manage the root directory and make it match the bundle structure.
The compliance option in the recipe tells the provisioning system whether to delete everything and force the directory to match the bundle content. The default is for that to be full, for the bundle to define the content and structure of the root directory. If the data in that directory must be saved, the compliance option can be set to filesAndDirectories, which means that provisioning will copy over the bundle and create the appropriate files and subdirectories, but it will not manage (remove) the existing content in the directory.

Warning

If you deploy a bundle to a high level directory like /etc on a platform or a critical directory like deploy/ or conf/, then all of the existing files and subdirectories in that directory are deleted. This can cause performance problems or data loss.
Bundles and Subdirectories

Even if the compliance option is set to filesAndDirectories, subdirectories and files contained in the bundle are always managed by the bundle, even if they existed before the bundle was deployed.

For example, the deploy/ directory has this layout before any bundle is deployed:
deploy/
deploy/notes.txt
deploy/myApp1/
deploy/myApp2/
deploy/myApp2/first.txt
A bundle is created with this layout:
myApp2/
myApp2/foo.txt
myApp2/bar.txt
If compliance is set to filesAdDirectories, the existing files in the deploy/ remain untouched, except for what is in the myApp2/ subdirectory, because that directory is defined by the bundle. So, the final directory layout is this:
deploy/ (ignored)
deploy/notes.txt (ignored)
deploy/myApp1/ (ignored)
deploy/myApp2/ (managed)
myApp2/foo.txt (managed)
myApp2/bar.txt (managed)

Note

Any existing content in the root directory is backed up before it is deleted, so it can be restored later.
The backup directory is /home/.rhqdeployments/resourceID/backup.
Files Added After the Bundle Is Deployed

After the initial deployment, there can be instances where files are added to the deployment directory, such as log files or additional data.

Within the deployment directory, the provisioning process overwrites any bundle-associated files with the latest version and removes any files that are not part of the bundle. Log files and other data — as with the root directory — need to be preserved between upgrades. Those known files and directories can be called out in the recipe using the <rhq:ignore> element, which tells the provisioning process to ignore those files within the deployment directory.

27.1.4. Requirements and Resource Types

By default, three resource types support bundles:
  • Platforms, all types
  • JBoss EAP 6 (AS 7) standalone servers[5]
  • JBoss EAP 5 and any server which uses the JBoss AS 5 plug-in
  • JBoss EAP 4 (deprecated)
Bundle support is defined in the plug-in descriptor, so custom plug-ins can be created that add bundle support for those resource types. For examples of writing agent plug-ins with bundle support, see Writing Custom JBoss ON Plug-ins.

27.1.5. Provisioning and Agent User System Permission

When a bundle is deployed, the provisioning process can write the bundle files to whatever directory on the system is specified, so long as the system user as which the agent is running has permissions to write to that directory.
As discussed in Chapter 4, Interactions with System Users for Agents and Resources, the system user which the agent uses is critical to the overall performance of JBoss ON. One the one hand, the system user must be joined to the appropriate groups and granted appropriate write access to manage resources effectively. On the other hand, especially when dealing with system content and configuration through bundles, it is critical that the agent user not be given excessive permissions, or the provisioning process itself could be used maliciously.
Whatever permissions the agent user has, the provisioning system and the deployed bundle can use. Every deployed bundle has the full system rights of the agent user.
Evaluating the required system permissions is critical when an agent is installed. It is also critical to evaluate what rights the agent user has and to plan the deployment path of a bundle — and even the content of the bundle itself — accordingly to prevent the deployed application or configuration files from making undesirable system changes or being used maliciously.

27.1.6. Provisioning and Roles

There are a set of bundle group-level and global permissions that are required for different management points for a bundle. The appropriate permissions must be granted to a role for a user to be able to manage bundles and deploy applications.
Bundle management breaks down into two types of tasks: creating bundle versions and deploying bundles to resources. The workflow for each of those processes is very much defined by the organizational structure, development process, and production rules. For example, in some environments, it may be permissible for anyone to create and delete new bundles and to deploy content to any resources which they have access to. In other organizations, it may be necessary to restrict bundle management to specific users or to divide tasks so that one group creates bundles while another user group deploys them.
The bundle permissions are listed in Table 9.1, “JBoss ON Access Control Definitions”, while a general example for planning permissions for different groups is covered in Section 9.4, “Extended Example: View All Resources, Edit Some Resources”.
The critical thing is to create a set of roles which parallel and reinforce the desired bundle deployment workflow — and this means that the workflow must be clearly defined and understood. The different parts of the provisioning process encompass two main relationships. Creating bundles (uploading them to the JBoss ON database) defines a bundle/user relationship. Deploying bundles (copying the content over to a resource) defines a bundle/resource relationship. The defined roles and permissions should reflect that.
Much like resources, bundles are defined in roles first by being members of bundle groups, and then the group itself is added to a role. By default, all bundles must be added to at least one group when they are created; they cannot be viewed and deployed until they belong to a group which belongs to a role with appropriate permissions to access it. There is one exception: users can be granted a global view bundles permission; this allows that user to create a bundle that is not in any group. The bundle remains in a holding state called unassigned, and only users with the view bundles permission can see it (which means, only they can add it to a group, assuming they have the appropriate permission). Creating bundle groups is covered in Section 27.7.1, “Managing Bundle Groups”.
Section 27.8, “Extended Example: Using Bundle Groups and Access Control within the Provisioning Process” covers some basic permissions models, defining different potential bundle/user and bundle/resource relationships.

27.1.7. Space Considerations for Bundles

Bundles can have a significant impact on disk space requirements.
JBoss ON stores all versions of content. This is part of versioning control, allowing changes to bundles to be reverted and managed and for different versions to be deployed at different times.
Therefore, the system which hosts the backend database (Oracle or PostgreSQL) must have enough disk space to store all versions of all bundles. Additionally, the database itself must have adequate tablespace for the content.
When calculating the required amount of space, estimate the size of every artifact, and then the number of versions for each artifact. At a minimum, have twice that amount of space available; both PostgreSQL and Oracle require twice the database size to perform cleanup operations like vacuum, compression, and backup and recovery.

27.1.8. Bundles and JBoss ON Server and Agent Plug-ins

27.1.8.1. Resource Support and the Agent Resource Plug-in

Whether provisioning is supported is defined in the resource type. For a resource type to allow provisioning, the resource plug-in descriptor must define a bundle target. That is the indication to the agent the provisioning is supported.
The <bundle-target> element simply defines allowed base directories for the resource which can be used as base directories in the bundle definition.
<server name="JBossAS:JBossAS Server" ...>
   <bundle-target>
      <destination-base-dir name="Library Directory" description="Where the jar libraries are">
         <value-context>pluginConfiguration</value-context>
         <value-name>lib.dir</value-name>
      </destination-base-dir>
      <destination-base-dir name="Deploy Directory" description="Where the deployments are">
         <value-context>pluginConfiguration</value-context>
         <value-name>deploy.dir</value-name>
      </destination-base-dir>
   </bundle-target>
</server>
Every resource plug-in descriptor defines a base directory, the root for all deployments, apart from provisioning configuration. For platforms, this is the root directory. For servers, it is usually the installation directory. The <bundle-target> can use the already-configured base directory or it can set different directories to use. In the example, two directories — the deploy/ and lib/ directories — are given as supported base directories. When a bundle definition is created, the wizard offers the choice of which directory to use.

27.1.8.2. Server-Side and Agent Plug-ins for Recipe Types

By default, JBoss ON supports one type of recipe, an Ant build file. However, other types of recipes could be supported because the recipe type is defined in a pair of plug-ins, one for the server and one for the agent.
The server-side plug-in tells the JBoss ON server how to manage bundles and destinations for that type of recipe.
The agent plug-in creates a child resource for the platform which is used to perform provisioning operations on the platform or target resource. For example, Ant bundles are actually deployed by the special JBoss ON resource, Ant Bundle Handler. This resource is added automatically to platforms as a child resource to enable Ant-based provisioning.

Note

Since recipe type support is implemented on the agent side through a special resource, that resource must exist in the JBoss ON inventory for it to perform provisioning. For example, without the Ant bundle handler in the inventory for a platform, JBoss ON cannot perform provisioning on that platform.
Administrators do not have to interact directly with the Ant bundle handler resource, but that child resource must be present in the platform's inventory for Ant provisioning to work.

27.1.9. Managing and Deploying Bundles with the JBoss ON CLI

Both uploading bundles to JBoss ON and deploying bundles to resources can be performed using the JBoss ON CLI.
The ability to script bundle deployments is very powerful, because it allows content or configuration updates, even new application servers, to be deployed automatically based on activity in other resources across JBoss ON. This is particularly useful with using JBoss ON CLI scripts in response to an alert:
  • A new JBoss application server can be deployed when an existing JBoss server experiences a heavy load or decreased performance.
  • Configuration files for a selected snapshot image can be immediately deployed to a platform or JBoss server to remedy configuration drift, in response to a drift alert.
  • A new web context can be deployed when another web is disabled within a mod_cluster domain.
Scripting also allows updates to be applied on schedule, such as having daily or weekly scheduled updates to a QE environment — which is also useful because the bundle content can be pulled from a GIT or SVN repository used by a build system first, and then deployed for testing.


[5] There is no defined deployment directory for servers in an EAP 6 domain. Deployments are handled centrally, through other mechanisms.