This article describes how to use ACE and is a good starting point for new users of Apache ACE. The remainder of this article assumes you have an ACE server and target up and running. Follow the getting started in 5 minutes guide in case you have not done so yet.
Introduction
Apache ACE is a framework that enables you to provision OSGi software (components) in a controlled manner. What this means is that you have a central server to which clients, or "targets" in ACE terminology, connect and fetch their software from. This allows one to control which target gets which software.
The software that is deployed to a target is composed of one or more distributions. A distribution is roughly similar to a piece of self-contained software. For example, it could be a plugin or even a full application. On their own, distributions consist of one or more features, that provide pieces of functionality to your software. The difference between a feature and distribution is that the former is not necessarily fully self-contained: it might need other features in order to operate properly. Each feature groups one or more artifacts. An artifact is anything from an OSGi bundle to a configuration file or any other kind of artifact that is needed for the software to work.
The artifacts themselves reside in an OSGi Bundle Repository (OBR). Think of an OBR as a repository, like the Maven repository or a content repository, storing immutable versions of artifacts1. You can use either the default OBR supplied by ACE or an external one, such as Sonatype's Nexus for storing your artifacts. As the OBR is the single source for all artifacts, and therefore the software that is deployed on a target, ACE is able to calculate how to upgrade a target from one version to another version. This is possible because all changes made to (the metadata of) ACE are stored in an internal versioned database. In other words, ACE always keeps a full history and audit trail for all changes, making it possible to go back and forth between versions deployed on each target.
Use cases and workflow
The typical use case for using ACE is where you want to control and manage which software runs on what target. So, how does one use ACE in practice? To explain the typical workflow of ACE, let's take the following example.
Assume you are working on a large OSGi-based system that provides some kind of service to your users (the exact details on what it does isn't relevant for this example).
As professional taking development seriously, you want to set up a DTAP environment. Your developers are working on their development machines, creating and using the latest, bleeding, edge of software they are working on. Even though they are smart guys that know the software inside out and can set up their own environments, they still might want to use ACE on their local machines to validate that changes they make indeed work when deployed. In this cases it makes sense to use the same deployment method that is used in production lateron as well.
There are also testers on your team, responsible for testing all the new features and bug fixes made by your developers. This tester does not want to have to set up his own environment and fiddle around with configuration files and such. Instead, he simply wants a working test environment that runs a recent version of the software, or even want to go back and forth between versions of the software. This is also were ACE can help you out. All you need to do is create targets for testing, on which a recent software version gets deployed. That "recent version", can, for example, be a nightly build that comes out of your CI server that automatically gets pushed to ACE after the nightly build is finished. Alternatively, the tester also can deploy an older version to his testing target through the ACE server UI, for example, to do some regression testing. A third scenario might be to duplicate the exact configuration and version that is currently deployed to a specific user's target.
Before a new version of your software is put into production, your users want to do acceptance testing to see whether this new version does not break anything. The acceptance environment should only be updated when a new version is released and after that remains as-is. In practice, this is most often not the case, as the acceptance environment is, when not used by any user, confiscated by your tester for its daily testing purposes, simply, because ACE allows him to easily deploy other versions to the acceptance environment. When a user asks for an acceptance test, he simply deploys the latest greatest official release to the acceptance environment, and lets the user do its testing. After that, he can repurpose it again. Another scenario obviously is that users setup dedicated targets for the purpose of acceptance testing.
When all acceptance tests are successful, the new version of your software needs to be deployed on several production environments, which is done by you, the release manager2. As most production environments only differ in a few details, such as IP addresses and maybe the database credentials, you use the template engine of ACE to make specific configuration files for each production target. This way, you can easily scale up your production environment by defining new targets and provide them with the necessary configuration values.
Workflow
Apache ACE can be used in many different workflows, which makes it rather difficult for new users to comprehend to use ACE to its full extent. By default, that is, without any configuration, the workflow of ACE is as follows (see also figure 1):
- a release manager2, ensures that the targets are defined. This is where the software is deployed and running. You can predefine each target using the ACE web UI, or start each target (and configure them properly to contact your ACE server) and make them appear automatically in your workspace (you might need to refresh your workspace before targets appear in the web UI);
- the release manager defines the features and distributions that need to be deployed. In the simplest case, you can define only one feature and distribution, but go also define much more fine-grained features and distributions if needed. The easiest way to define features and distributions and to link them to each other is by using the ACE web UI. This allows you to simply use the "add" buttons and drag-and-drop to achieve this;
- the artifacts are added to your OBR. This can be done by uploading them through on of the ACE clients, for example, the web UI. Once uploaded, the artifacts need to be linked to features in order to be deployed to targets. Again, the ACE web UI makes this easy by simply using drag-and-drop to link artifacts to features;
- the next time the target contacts the ACE server, it will retrieve the configured distribution(s);
- If you linked artifacts to features using the ACE web UI, it will create "wildcard" assocations, meaning that it will automatically use the latest version available for each artifact. This means that if you update existing artifacts in the OBR, ACE will automatically deploy them to all affected targets. If you add new artifacts, you need to link them to existing or new features and distributions to deploy them.
Figure 1: A graphical overview of a typical workflow of ACE (click on image to see full size).
Working with the ACE Server
The ACE web UI (see figure 2) might look a bit daunting at first, but once you become more familiar with it, you'll see that it is rather easy to work with.
Figure 2: The server UI of ACE after logging in, showing the control area at the top, and the resource area below that (click on image to see full size).
After logging in, the main window consists of two main areas:
- The control area at the top of the screen, where you can perform actions like retrieving the latest repository changes, revert the changes you've made locally, add new artifacts, and so on;
- The resource area, consisting of (up to) four columns showing the current artifacts, features, distributions and targets that are known to ACE. When you select an entity here, the associated entities in other columns will automatically be highlighted, giving you an instant overview of the links within the system.
Apache ACE allows for concurrent use at every aspect. Many targets can request different versions of software that need to be served, while at the same time one or more users are uploading artifacts and/or defining new features or distributions. To support this, ACE has the concept of a "workspace". This somewhat resembles a VCS you might already use for your software development. Prior to making changes, you need to "check out" a workspace in an ACE client. In the web UI, this is done implicitly if you hit the "Retrieve" button. Once the workspace is checked out, you can make any changes you want, that is, create features, distributions, targets and/or create links between them. If you are finished, you need to "commit" your workspace back to the ACE server to persist the changes. Committing your changes in the ACE web UI is done by using the "Store" button. The "Revert" button can be used to throw away your changes in the web UI. Note that this does not retrieve the latest changes from the ACE server! This is only done when using the "Retrieve" button.
Uploading artifacts
The easiest way to add one or more new artifacts is by simply dragging and dropping them on the artifact column. Note that a drop is accepted only when a blue line or border is shown around the artifacts column (see figure 3). The artifacts are uploaded automatically in the background, and when they are complete, a summary of the upload results is shown as notification (see figure 4).
Figure 3: Adding new artifacts by dragging them onto the artifacts column. Note the blue line surrounding the artifacts column denoting the drop can be accepted (click on image to see full size).
Figure 4: A notification is shown when all artifacts are successfully uploaded (click on image to see full size).
To add artifacts that are already in the OBR, you click the "Add artifact..." button. An "Add artifact" dialog opens, showing the artifacts currently in the OBR (but not yet in the list of selected artifacts) and a list of to-be-uploaded artifacts. This window also allows you to upload artifacts, and offers two options to do so:
- by uploading the individual artifacts by pressing the "Upload" button and selecting the artifact from the file chooser dialog, or;
- by using drag-and-drop: select all artifacts in an Explorer or Finder and drag them onto the "Upload artifact" area. This way, you can upload multiple artifacts in one go.
If you try to upload an artifact that is not recognized by ACE, a failure notification is displayed noting that that particular artifact is not uploaded (see figure 5). Adding support for new types of artifacts in ACE is discussed in more details in this article.
Figure 5: A failure notification is shown when one or more artifacts could not be recognized by ACE.
Once all artifacts are uploaded, they appear as selected rows in the artifacts column. You
can immediately drag them onto the feature column to link them to a particular feature. By
double clicking on an artifact, you can edit some of its properties, for example, its
description.
To remove an artifact from the artifacts column, you simply press its trash-can icon. Note
that removing an artifact will only remove it from the artifacts column, not from the
OBR.
A very important concept to remember is that all metadata in Apache ACE is stored in versioned databases. This makes it possible to determine what differences there are between (any) two versions, but only if all artifacts in the OBR also remain the same once they are uploaded. This is why ACE does not allow you to add the same artifact twice.
NOTE: As described earlier, all changes made through the Web UI need to be stored explicitly by pressing the "Store" button or by hitting CTRL+S (or CMD+S if you happen to use OSX), otherwise they will not be visible to the ACE server. In case you want to revert all changes, you can use the "Revert" button or CTRL/CMD+U. This will ignore all local changes but does not retrieve the latest state from the server. To retrieve the latest state from the server, use the "Retrieve" button or CTRL/CMD+G.
Creating a new feature, distribution and/or target
Adding features and distributions are very similar. You either click the "+" button above the features column, or the "+" button above the distributions column. Alternatively, you canuse the shortcut keys CTRL/CMD+F and/or CTRL/CMD+D to add new features/distributions. In both cases, you are presented with a dialog that allows you to enter the (mandatory) name of the feature or distribution and an optional description.
To define a new target in the ACE web UI, you can do either:
- pre-register a target by clicking the "+" button above the targets column and entering the name of the new target. This allows you to associate software to this target before it has ever been started or seen by the server; or,
- you can register a target that is already running and has already tried to fetch software from the ACE server. The details on this will be discussed later on.
After a feature, distribution or target is created, you can edit its properties by double clicking it. For features and distributions, this means you can alter their description, while for targets, there are more possibilities to view and alter:
- On the Management tab, you can register a target, and change whether or not changes to any distribution associated to that target should be automatically approved to make the target obtain the latest software. If auto-approve is enabled, all updates will automatically be approved and distributed to that target. If not, all updates must be explicitly approved prior to being distributed to the target. For convenience, the "A" button above the targets column in the main UI allows you to approve the changes for one or more (selected) targets. The "R" button allows you to register one or more selected targets in a single go;
- On the Info tab, you can view the current state of the target, such as the currently installed version, or the latest available software version;
- On the Log Viewer tab, you can view the installation log of the target. This allows you to review the installation of updates on that target;
- The Tag Editor tab allows you to define tags and their values (see also figure 8). Tags can be used for many things, but one of their more interesting use cases is that they can be used to replace variables in template artifacts that contain those tags. This is useful, for example, to have a single configuration file that can be used for multiple targets, because it is largely the same for all of them;
- The Verify/resolve tab provides a basic facility to verify whether a particular distribution will actually resolve on the target.
Creating associations
To link artifacts to features, you simply select the artifact and drag it on top of the feature to which it should be associated. The same principle also applies if you want to associate features to distributions and distributions to targets. To delete an association once is created, you can click either the left- or the right hand side of the association (viz. either the artifact or the feature), and click the "broken chain" button on the opposite side of the association. For example, to delete an association between an feature and distribution, you can select the feature first, and hit the "broken chain" button on the distribution. Alternatively, you can select the distribution first and hit the "broken chain" button on the feature to delete the association.
There is a subtle, but very important, difference when you associate a bundle-artifact to a feature by dragging its symbolic name (without a version) onto a feature, or when you drag a bundle-artifact with a version onto a feature. In the first case, you make a "dynamic" association (see figure 6), which states that you always want the latest version of that bundle to be associated to the feature, including any newer version that might be uploaded in the future. In the latter case, you make a "static" association (see figure 7), which states that you always want that particular version of that bundle to be associated to the feature.
Figure 6: Creating a dynamic association by dragging the BSN of a bundle onto a feature.
Figure 7: Creating a static association by dragging a particular version of a bundle onto a feature.
Creating dynamic associations is currently only supported for bundle artifacts. For other types of artifacts, such as configuration files, only static associations can be created4.
Configuring the server
The ACE server is completely modular and therefore can be configured in many different ways. As such, the configuration of the server is done by using the Configuration Admin service which is provisioned by means of configuration files that reside in the conf directory. The filename of each configuration file equals the service PID of the managed service and must end with .cfg. Directories are considered as managed service factories of which the directory name equals the service PID.
Configuration files itself are simple Java property files containing key-value pairs separated by newlines. Configuration values are allowed to contain "placeholders" or "variables". Everything between ${ and } is considered a variable and replaced by the value represented by that variable. For example, consider a variable var that is defined as "value", then ${var} will be replaced with "value". Variables can refer to another value in the same configuration file, or to a property that is defined in the OSGi-framework or globally in your system as environment setting.
The configuration files are watched continuously in the background, allowing you to adjust the configuration of the ACE server at runtime without having to restart it.
Running a target
As mentioned, a target represents a client on which software can be deployed by ACE. Actually, a target consists of an OSGi runtime that runs at least the ACE management agent. This management agent periodically checks with the ACE server whether or not new software is available. In case new software is available for a target, it can automatically download and install it.
ACE provides a single runnable JAR target.jar that starts an OSGi runtime, the
ACE management agent, and a Gogo shell for easy debugging and demo purposes. It is also
available in the ACE source repository as Eclipse project called run-target.
The management agent, or agent for short, does the following:
- it uploads the audit log of the target to the ACE server. The audit log contains all changes in bundle and framework state, such as the starting and stopping of the framework and (de)installation of bundles;
- it check whether or not software updates are available. If so, it will download it and install this update automatically.
To run a target, you need to issue the following command:
$ java \ -Dagent.identification.agentid=target-1 \ -Dagent.discovery.serverurls=http://my.ace.server:8080 \ -jar target.jar ____________________________ Welcome to Apache Felix Gogo ...
Target configuration
The agent can be configured by supplying its options as commandline parameters (e.g. -Dname=value). A list of most used options are8:
- agent.identification.agentid
- defines the name to uniquely identify a target on the ACE server. In case this option is not supplied, a default value of defaultTargetID is used;
- agent.discovery.serverurls
- defines the ACE server URLs to connect to. Multiple URLs can be given to get a form of fail-over: in case a connection to the first URL cannot be established, the second URL will be used, and so on. If this option is given, at least one URL should be supplied, and multiple URLs can be supplied by separating them with a comma. If this option is omitted, a default value of http://localhost:8080 is used;
- agent.discovery.checking
- defines whether or not server URLs should be checked whether they are alive prior to being used. This implies that a "ping" request is sent to the server URL that is going to be used. Server URLs that are not responding will not be used and will cause another URL (defined by agent.discovery.serverurls) to be picked instead. The default value is true, which means that all server URLs are checked. Use false if your ACE server(s) are not always available or when running the target on a flacky network;
- agent.logging.level
- defines the log level of the agent, and should be one of the following values: DEBUG, INFO, WARNING or ERROR. The default log level is INFO;
- agent.controller.syncinterval
- defines the interval (in seconds) in which the agent should synchronize with the ACE server. A default of 60 seconds is used in case this option is not supplied;
- agent.controller.syncdelay
- defines how long the agent should wait (in seconds) after startup before it will synchronize with the ACE server for the first time. A default of 5 seconds is used in case this option is not supplied;
- agent.controller.streaming
- if given a value of false, all software updates will be downloaded completely first after which it will be installed. Use this value in case you suffer from unreliable network connections. A value of true (the default) causes the agent to download and install any software update directly.
- agent.controller.fixpackages
- if given a value of true (the default), software updates will only contain the deltas or changed artifacts. For large deployment packages, this can dramatically reduce the size of an update. Use a value of false to always get all artifacts for each software update;
- agent.controller.retries
- defines the number of times the agent should retry to install a software update in case its installation fails. If omitted, an installation is retried 3 times;
- agent.feedback.channels
- defines what feedback channels exist and should be synchronized with the ACE server. Feedback channels can be used to report any kind of information back to the ACE server, and is by default used to provide basic information on the OSGi environment to the ACE server. If omitted, the default of auditlog is used. Multiple feedback channels can be supplied by separating them with commas, like auditlog,myOwnLog. Note that all mentioned feedback channels must be configured on the ACE server as well;
- agent.logging.events.exclude
- defines the audit events that should be excluded from appearing on the audit feedback channel. This parameter takes one or more event types represented by integers separated by commas, for example, 2001,2003,2005,3001. By default, no events are excluded;
- agent.connection.authtype
- defines how to connections to the server are to be authenticated. Valid values are NONE for no authentication, BASIC for using HTTP-BASIC authentication or CLIENTCERT for using client certificates. In case this option is omitted, a value of NONE is assumed and no authentication is used. In case of the values BASIC or CLIENTCERT, additional options should be supplied (see below);
- agent.connection.username and agent.connection.password
- provide the username and password used for HTTP-BASIC authentication;
- agent.connection.sslProtocol
- defines what SSL protocol is to be used for creating secure connections to the ACE server, defaults to TLS;
- agent.connection.keyfile and agent.connection.keypass
- provide the keystore file and password that contain the certificate information for establishing a secure conncetion between agent and server;
- agent.connection.trustfile and agent.connection.trustpass
- provide the truststore file and password that contain the trusted (server) certificate(s) for establishing a secure connection between agent and server.
When the agent is started, a new target should appear in the ACE server after you
"Retrieve" the latest changes in the web UI. Note that this can take a little while since
the agent needs to synchronize with the server first, see
agent.controller.syncdelay and agent.controller.syncinterval options
above. If a new target is seen this way by an ACE server instead of adding it through the
"+" button above the targets column, it initially will be unregistered. This means that
no metadata is present in the ACE server yet and will not be created.
To register a target, you can either double click the target. On the "Management" tab, you
can check the "Registered?" option (and optionally the "Auto approve?" option as well) and
close the dialog by pressing "Ok"3. Once a target is registered, it cannot be
unregistered unless it is deleted using the trash-icon. Alternatively, you can register
one or more targets directly by selecting them and pressing the "R" button above the
targets column.
Using the template engine for targets
If you want to provision software to multiple targets, each of those targets probably need to have their own specific configuration. For example, the IP address on which it should listen for web requests, or the credentials to access a database. One could create specific configuration files for each target, however, this can become quite tedious if you have lots of targets. Besides that, ACE requires that each artifact has a unique name, so you need to create unique file names for your configuration files for each change you make. Fortunately, ACE provides an easier way to solve this problem: a template engine.
All configuration files5 can be regarded as templates, in which variables are replaced
with values supplied by ACE. In fact, the values are definable per target, distribution,
feature or artifact and ACE will collect all tags of entities that are associated with a
specific target. To define variables and their replacement values (or "tags") for, for
example, a distribution, open up its properties dialog by double clicking on it, and
selecting the "Tag Editor" tab. Each line in this editor represents a tag. The key of a
tag defines that (part of) the variable name to be replaced in configuration files, and
the value of a tag the actual replacement value.
In order to let ACE provision your (templated) configuration files to your target, you
need a resource processor that is capable of handling the configuration files. Without
such a resource processor, the configuration files cannot be deployed to your target. See
this article for more information about writing
resource processor for your configuration files, or use an existing one, such as Felix
Autoconf resource
processor.
Suppose a valid resource processor is available that recognizes Java Properties XML, consider the following configuration file:
<properties version="1.0"> <entry key="ipAddress">${context.address}</entry> <entry key="port">${context.port}</entry> <entry key="logLevel">INFO</entry> </properties>
The ${context.address} and ${context.port} represent variables that can be replaced. The context. (including the dot) prefix is mandatory, and everything after this prefix is user-definable and considered as variable name. In this example, two variables are expected: address and port. The values for these variables can be added to entities by using the "Tag Editor", available when you double click on an artifact, feature, distribution or target in the web UI6. It does not really matter on what entity the variables are actually defined, but in most cases they are either defined on a distribution and/or target.
Suppose we want to deploy the aforementioned configuration file to two targets, "target-1", which is supposed to listen on 192.168.2.1:80 and "target-2", which is supposed to listen on 192.168.2.2:8080. To make the configuration file specific for both targets, we simply need to define two tags on "target-1", like (see also figure 7):
- address -> 192.168.2.1;
- port -> 80.
And similar tags on "target-2":
- address -> 192.168.2.2;
- port -> 8080.
Figure 8: Using the Tag Editor of a target to supply configuration variables.
Under the covers, ACE uses Velocity7 to parse the template. This means that, apart from variable substitution, you can also use other Velocity macros and create more complex configurations that might contain conditional sections, loops and other features Velocity provides. See the Velocity documentation for more information on how to use this functionality.
In case a variable cannot be resolved, it will simply not be replaced, but left as-is. This could lead to invalid or unparsable artifacts (configuration files) on your target!
ACE will scan all configuration files and replace all known variables as soon as a new deployment is created. This means that for our example, both "target-1" and "target-2" will get a processed version of the configuration file, each with its own specific content. ACE also automatically versions these generated files, to aid downgrading software.
-
Once an artifact is uploaded to the OBR, it cannot be modified anymore. This is necessary in order to allow both software upgrades as downgrades and to ensure that everything you do is reproducible. One thing to note is that this is not compatible with the way that Maven handles snapshot versions. A snapshot can contain anything. In stead we usually use the version qualifier to append a timestamp in such scenarios. ↩
-
To read more about the various roles used in Apache ACE, see this page; ↩
-
This is a limitation of the current web UI. It is possible to create more sophisticated associations by using the REST API or the Gogo shell commands. ↩
-
Do not forget to store your changes! ↩
-
In fact any artifact can be considered as an template, but by default ACE only considers configuration files. ↩
-
In other UIs, such as the Gogo shell, you need to supply these tags manually. ↩
-
Apache Velocity is an engine that can generate documents by combining a template with a context that contains variables. To learn more about it, visit the Velocity website. ↩
-
A complete list of recognised options can be found in org.apache.ace.agent.AgentConstants. ↩