© 2018 The original authors.
1. Overview
Galleon is a provisioning tool designed to create and maintain software distributions that consist of one or more products (or components). The tool supports:
-
adding products to a distribution;
-
their default and customized configurations;
-
-
removing products from a distribution;
-
integration of the products in the distribution;
-
resolution and validation of the resulting configuration and runtime dependencies;
-
patching and version updates;
-
product-specific provisioning plugins;
-
detection of the changes in the provisioned distribution (its filesystem content and/or its configuration) applied by the user manually or by means of other management tools
-
to be able to preserve them after a version upgrade (having made sure the changes are compatible in the new version)
-
or create a provisioning configuration that could be used to reproduce the state of the distribution including the user changes;
-
-
exporting the provisioning configuration of the current state of the distribution with the goal to reproduce it later at another location.
The tool includes a command-line interface and a public API. There is also a Maven plugin that allows provisioning a distribution according to the provided configuration.
Releases of the command line tool are available on the Galleon releases page.
Download and unzip the release zip and add the bin
dir to your system path. Use galleon.sh
or galleon.bat
to launch the tool.
2. Feature-packs
Feature-pack represents a released unit of software (project, product, component, etc) that can be installed or uninstalled using Galleon tools. Feature-packs are ZIP archives that are normally deployed by the feature-pack producers to artifact repositories (such as Maven) where they can be discovered and consumed by users using Galleon tools.
Feature-pack contains:
-
metadata describing
-
dependencies on other feature-packs;
-
the default configuration(s) of the product the feature-pack represents;
-
the package set that should be installed by default;
-
-
(optional) a set of packages (that represent various filesystem content);
-
(optional) a set of configuration feature specs (used to define and/or tune parts of the product configuration);
-
(optional) various resources required to properly assemble and configure the product;
-
(optional) product-specific provisioning plug-ins.
Feature-pack may declare dependencies on other feature-packs. Before a feature-pack is installed the tool will make sure its dependencies are satisifed (by installing the missing ones). |
2.1. Feature-pack archive structure
Feature-packs are distributed as ZIP archives with the following root entries:
feature-pack.zip |- configs/ |- feature_groups/ |- features/ |- layers/ |- packages/ |- plugins/ |- resources/ `- feature-pack.xml
Where
-
configs - optional directory containing predefined installation configurations;
-
feature_groups - optional directory containing feature group descriptions;
-
features - optional directory containing feature specs (units of configuration);
-
layers - optional directory containing predefined configuration layers that can be used to create custom installation configurations;
-
packages - optional directory containing packages (units of filesystem content);
-
resources - optional directory containing various resources needed to properly assemble and configure the product;
-
plugins - optional directory containing product-specific provisioning plug-ins (note, that alternatively plugin artifacts can also be referenced from
feature-pack.xml
using their repository coordinates); -
feature-pack.xml - metadata describing the feature-pack and the default product configuration.
2.2. Feature-pack metadata (feature-pack.xml)
Generally, feature-pack metadata contains the following information:
-
Feature-pack location - string expression that indicates how to resolve the feature-pack artifact from a remote repository and how it can be identified among other feature-packs;
-
(optional) dependencies - dependencies on other feature-packs.
-
(optional) configuration - the default configurations of the product (there could be more than one default configuration);
-
(optional) default packages - names of the packages that are installed by default.
-
(optional) plugins - various provisioning plugins.
-
(optional) system-paths - paths to files that should be protected during upgrades.
Here is an illustration of how it may look like in a feature-pack.xml
file:
<feature-pack xmlns="urn:jboss:galleon:feature-pack:3.0"
location="wildfly-servlet@maven(org.jboss.universe:community-universe):current#14.0.0.Beta2"> (1)
<dependencies>
<dependency location="wildfly-core@maven(org.jboss.universe:community-universe):current#6.0.0.Beta1"/> (2)
</dependencies>
<config model="standalone" name="standalone.xml"> (3)
<feature-group name="standalone"/>
<feature spec="another-feature">
<param name="p1" value="v1" />
<param name="p2" value="v2" />
</feature>
</config>
<config model="domain" name="domain.xml">
<feature-group name="domain"/>
</config>
<config model="host" name="host.xml">
<feature-group name="host"/>
</config>
<default-packages> (4)
<package name="docs"/>
<package name="modules.all"/>
</default-packages>
<plugins> (5)
<plugin location="org.jboss.galleon.example:galleon-example-plugin:1.0.0.Final"/>
</plugins>
<system-paths> (6)
<system-path path="modules/system/layers/base"/>
</system-paths>
</feature-pack>
1 | Feature-pack location and build info |
2 | Dependency on another feature-pack |
3 | Description of the default standalone.xml configuration |
4 | List of packages that should be installed by default |
5 | List of provisioning plugins |
6 | List of protected system paths |
2.3. Feature-pack location
Feature-pack location is an expression that is used to resolve the feature-pack artifact from the remote repository and also identify the feature-pack among other feature-packs.
The general and complete feature-pack location format is producer@universe:channel/frequency#build
-
producer - simple name of a feature-pack producer, normally a product or a component name;
-
universe - the universe the producer belongs to (universe is basically a named set of feature-pack producers);
-
channel - source of backward compatible feature-pack builds;
-
frequency - denotes the lowest accepted build quality (e.g. alpha, beta, final, etc) for the feature-pack builds pulled from the channel;
-
build - feature-pack build number or version.
Some of the parts above are or could be optional. For example, a user could add a specific universe as the default one for the distribution (in its provisioning configuration) and then not include it explicitly into feature-pack locations for the feature-packs coming from that universe.
Frequency is, generally, also optional and could be omitted.
Feature-pack producer may configure a default channel, which makes the channel part optional for the feature-packs of that producer.
With the universe and frequency omitted the location becomes producer:channel#build
Here is an example of a full feature-pack location:
wildfly@maven(org.jboss.universe:community-universe):current/beta#17.0.0.Beta1
And a shortened version:
wildfly:current#17.0.0.Beta1
And assuming current
is the default channel it becomes
wildfly#17.0.0.Beta1
Galleon CLI tool comes pre-configured with maven(org.jboss.universe:community-universe) as the default universe, which means Galleon CLI users can omit the universe part for wildfly and other feature-pack producers from that universe and also, in general, rely on TAB-completion for feature-pack locations.
|
Using Galleon CLI
install wildfly@maven(org.jboss.universe:community-universe):current/beta#17.0.0.Beta1
and
install wildfly#17.0.0.Beta1
will result in the exact same distribution. And to install the latest (final) version of wildfly
a user can simply type
install wildfly
2.3.1. Channel
Channel represents a source of backward compatible releases. Channels are defined and configured by feature-pack producers.
As an example, a channel could be mapped to a major version of a product. Suppose, there is product productA
with development branches 1.x
and 2.x
and 2.x
branch is not backward compatible with 1.x
branch. In this case, the producer of productA
could define two channels 1
for branch 1.x
and 2
for branch 2.x
. Then, to install the latest available (final) release of 1.x
branch the user would request the tool to install productA:1
and productA:2
for the latest available (final) release on 2.x
branch.
2.3.2. Frequency
Frequency is a channel option that indicates the lowest acceptable build quality when the tool is looking for the latest build of the product. Supported frequencies are defined and configured by feature-pack producers. If the user has not provided any frequency, the default is assumed to be the final (or GA) release.
Frequency is used by the provisioning mechanism only when looking for the latest build. I.e. when installing a product for which the user has not specified the version or when looking for updates for the already installed products. |
The following is a valid feature-pack location expression: productA:1#1.0.0.Beta2
.
Although the frequency is missing, which means it’s equivalent to productA:1/final#1.0.0.Beta2
. Installing productA:1#1.0.0.Beta2
will still install 1.0.0.Beta2
, because the user has provided the desired version explicitly.
But if the user requests an update to the latest version, the tool will check the frequency and will look for the latest available release that satisfies the frequency. In the example above, the tool will not update the distribution until 1.0.0.Final
becomes available, even if 1.0.0.Beta3
becomes available before that.
However, if the user installed the same feature-pack as productA:1/beta#1.0.0.Beta2
and requested an update to the latest version, the tool would also look for the available beta releases and propose 1.0.0.Beta3
if it’s available.
frequency specifies the lowest quality, which mean installing productA:1/beta may actually install 1.0.0.Final if the final release is available.
|
2.3.3. Feature-pack Maven Artifact Location
It is also possible to use the feature-pack’s Maven artifact coordinates in place of the feature-pack location expression described above. In that case, after the feature-pack artifact has been resolved, its actual Galleon feature-pack location will be used during provisioning and state persistence. E.g.
install org.wildfly:wildfly-galleon-pack:17.0.0.Final
will be equivalent to
install wildfly#17.0.0.Final
3. General provisioning workflow
This is not a precise description of how it happens but a high level overview of the workflow.
-
The provisioning mechanism determines a set of feature-packs that need to be resolved for the installation
-
Feature-pack version compatibility is checked
-
The feature-packs are downloaded from their respective repositories and unpacked in a temporary location
-
Feature-packs are processed in the order they are specified in the installation provisioning description
-
configuration models and the packages set to be installed is determined for every feature-pack
-
configuration models are merged on-the-fly as soon as they are processed
-
-
A staged directory is created
-
Content from all the feature-pack packages is copied to the staged directory (in the order the feature-packs should be installed)
-
Feature-pack plugins are invoked
-
The plugins are assumed to generate the configuration files from the provided resolved configuration models and perform other necessary tasks to complete the installation
-
-
The provisioned state of the installation is recoded
-
The installation created in the staged directory is moved to the target installation directory (fully replacing the current one, if it exists)
-
The temporary directories are deleted
4. Feature-pack packages
A package is a minimal atomic unit of filesystem content that can be included into or excluded from the installation. It could be a set of files and/or provisioning-related resources attached to the package used by the mechanism to provision a piece of filesystem content.
Essentially, a software release (filesystem content-wise) is represented as a set of packages released under a common version.
Package contains:
-
metadata describing the package;
-
(optional) FS content which is copied into the installation when the package is installed;
-
(optional) other provisioning resources that are used during provisioning to generate and/or integrate the content (or what the package represents) properly into the target installation.
Package may declare dependencies on other packages that belong to the same or another feature-pack. Before a package is installed, the tool will make sure all its dependencies are satisifed (which includes automatic installation of the ones that are missing from the installation).
Package is identified by its name. The name must be unique in the scope of the feature-pack the package belongs to.
Packages are not versioned. Only the feature-pack has a version.
4.1. Package directory structure
Packages are stored in the directories (named after the packages) under the feature-pack packages
directory.
Package directory contains the following entries:
-
package.xml - the metadata describing the package;
-
(optional) content - directory containing the content of the package which will be copied to the installation when the package is installed;
-
(optional) pm - directory containing various resources needed to properly provision the content of the package.
Here is an illustration of packages
entry from a feature-pack archive containing packages p1
, p2
, p3
and p4
:
packages/ |-p1/ | |-content/ | | `-... | |-pm/ | | `-... | `-package.xml |-p2/ | |-content/ | | `-... | `-package.xml |-p3/ | |-pm/ | | `-... | `-package.xml `-p4/ `-package.xml
4.2. Package metadata (package.xml)
Package metadata contains the following information:
-
package name;
-
(optional) dependencies - dependencies on other packages from the same and/or other feature-packs;
Here is an illustration of how package.xml
might look like:
<package-spec xmlns="urn:jboss:galleon:package:2.0" name="p1">
<dependencies>
<package name="p2"/>
<package name="p3" optional="true"/>
<origin name="another-feature-pack">
<package name="p1"/>
<package name="p11" optional="true"/>
</origin>
</dependencies>
</package-spec>
Here package p1
declares dependencies on packages p2
and p3
that belong to the same feature-pack as p1
and packages p1
and p11
that belong to another feature-pack referenced by alias another-feature-pack
.
4.3. Package dependencies
Required dependency means that a package cannot be installed unless all its required dependencies are satisfied, i.e. installed. If any required dependency cannot be satisfied (perhaps because a package that happens to be a required dependency has been explicitly excluded from the installation), the provisioning process will fail with an error.
Optional dependency means that the dependency does not have to be satisfied for the package to be installed. For example if package p1
declares an optional dependency on package p2
and p2
is explicitly excluded by the user, p1
will still be installed. An example of an optional dependency could be a package called documentation
which declares an optional dependency on package examples
. If a user is not interested in examples
, the rest of documentation
could still be installed.
Package dependencies are also used to determine the effective package set of a feature-pack to be installed described later.
Here is an example of how dependencies are expressed in the XML metadata:
<package-spec xmlns="urn:jboss:galleon:package:2.0" name="p1">
<dependencies>
<package name="p2"/> (1)
<package name="p3" optional=”true”/> (2)
</dependencies>
</package-spec>
1 | required dependency on package p2 |
2 | optional dependency on package p3 |
A package may declare dependency on a package from the same or another feature-pack. During the dependency resolution, at first, the mechanism is trying to resolve the package dependency locally, i.e. in the current feature-pack. If the dependency could not be resolved locally, the mechanism will look for the package dependency in the feature-packs the current feature-pack depends on (in the order the feature-pack dependencies are listed in feature-pack.xml
of the current feature-pack). The first found matching package will be used as the resolved dependency. If the package dependency could not be resolved, the mechanism will report an error.
Although a package may declare a dependency on a package from another feature-pack, it cannot specify the version of the feature-pack in the package dependency declaration. |
4.3.1. Passive dependencies
An optional dependency may be also marked as passive, e.g.
<package-spec xmlns="urn:jboss:galleon:package:2.0" name="p1">
<dependencies>
<package name="p2" optional=”true” passive="true"/>
</dependencies>
</package-spec>
Or, in fact, the example above can be re-written without optional="true"
since only optional dependencies can be passive, i.e.
<package-spec xmlns="urn:jboss:galleon:package:2.0" name="p1">
<dependencies>
<package name="p2" passive="true"/>
</dependencies>
</package-spec>
A passive dependency on a package is satisified only if all the required dependencies of that package are included into the installation (as the default packages or direct or required dependencies (possibly transitive) of the provisioned configs, layers, feature groups or features). |
Passive dependencies affect how the effective package set of a feature-pack is resolved.
4.3.2. Explicit package dependency origin
Feature-pack containing a package with an external dependency must declare an explicit dependency on the feature-pack (specifying its version) the target package of the external dependency belongs to. This feature-pack dependency may also be assigned a name which can later be used as a reference to that feature-pack dependency when declaring dependencies in package.xml
file on packages that belong to that feature-pack.
For example, suppose feature-pack fp1
depends on feature-pack fp2
and package fp1:p1
depends on packages fp2:p1
and fp2:p10
. The feature-pack.xml
of fp1
might look like this:
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
<dependencies>
<dependency location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0">
<origin>fp2-dep</origin>
</dependency>
</dependencies>
<default-packages>
<package name="p1"/>
</default-packages>
</feature-pack>
And the package.xml
file of fp1:p1
might look like this:
<package-spec xmlns="urn:jboss:galleon:package:2.0" name="p1">
<dependencies>
<package name="p2" />
<origin name=”fp2-dep”>
<package name=”p1” />
<package name=”p10” />
</origin>
<package name="p3" />
</dependencies>
</package-spec>
In general, the origin
element is optional, but in some cases it helps to specify explicitly the origin of package dependencies.
4.4. Feature-pack default packages
Feature-pack may define a set of default packages. This set of default packages is installed when the user does not provide explicit instructions about which packages from the feature-pack to install.
Default packages are explicitly listed in feature-pack.xml
file which is a part of the feature-pack archive. For example:
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
<default-packages>
<package name="package1" />
<package name="package2" />
</default-packages>
</feature-pack>
If this feature-pack is installed without further customizations, package1
and package2
will be installed by default, although the feature-pack above may still contain other packages (not listed as default) that may not get installed.
4.5. Feature-pack non-default packages
Feature-pack may contain packages that are not marked as default in its feature-pack.xml
. Non-default packages can be installed either:
-
implicitly, in case a non-default package appears to be a transitive dependency of a default package;
-
explicitly, in case a user explicitly selected a non-default package to be installed.
4.6. Effective package set
This chapter is dedicated to the effective package set of a feature-pack (without dependencies) that is going to be installed, how it is resolved by the mechanism and how it can be adjusted by a user.
4.6.1. Feature-pack original effective package set
Original in the title means not explicitly modified. I.e. the set of packages which is going to be installed when the feature-pack is installed as-is without any customizations from a user.
Generally speaking, the original effective package set of a feature-pack consists of all the default packages of the feature-pack plus all the packages that appear to be direct or transitive dependencies of the default packages, the default configs and layers, feature groups and features those configs consist of.
While the required package dependencies are always included into the effective package set, the inclusion of optional packages can be controlled with one of the policies specified as the value of provisioning option optional-packages
: all
, none
, passive
and passive+
.
Here is the table illustrating which dependency types are automatically included and which are filtered out form the effective package set under each policy:
all |
passive+ |
passive |
none |
|
required |
+ |
+ |
+ |
+ |
passive (satisfied) |
+ |
+ |
+ |
- |
passive (unsatisfied) |
+ |
- |
- |
- |
optional |
+ |
+ |
- |
- |
4.6.2. Explicit package exclusion
A package may be explicitly excluded from the feature-pack’s effective package set. For example, given the following feature-pack definition (feature-pack.xml
):
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
<default-packages>
<package name="p1" />
<package name="p2" />
</default-packages>
</feature-pack>
and assuming that
-
package
p1
has an optional dependency on non-default packagep11
, -
package
p2
has an optional dependency on non-default packagep22
.
The original effective package set of fp1
includes p1
, p11
, p2
and p22
.
If a user is interested in a subset of the effective package set, in fact, only in package p1
, for example, it can be expressed in the provisioning XML configuration file as
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
<packages>
<exclude name="p11"/>
<exclude name="p2"/>
</packages>
</feature-pack>
</installation>
Packages p11
and p2
are explicitly excluded and package p22
is a non-default package which is not a direct or transitive dependency of the packages to be installed, i.e. p1
.
4.6.3. Explicit package inclusion
A package may be explicitly included into the feature-pack’s effective package set. For example, given the following feature-pack definition (feature-pack.xml
):
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe:1#1.0.0" >
<default-packages>
<package name="p1" />
<package name="p2" />
</default-packages>
</feature-pack>
and assuming that
-
p2
has an optional dependency on non-default packagep21
, -
fp1
also contains non-default packagep3
, -
p3
has an optional dependency on non-default packagep31
.
The effective package set of fp1
includes p1
, p2
and p21
.
A user may explicitly add package p3
, exclude p2
and still leave p21
in the effective package set using the following configuration:
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
<packages>
<include name="p3"/>
<exclude name="p2"/>
<include name="p21"/>
</packages>
</feature-pack>
</installation>
The effective package set now will consist of p1
(default package), p21
(explicitly included non-default), p3
(explicitly included non-default) and p31
(brought in as a dependency of p3
).
If, for example, the user wanted to further cut down the effective set to p21
and p3
, the configuration would change to
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
<packages>
<exclude name="p1"/>
<exclude name="p2"/>
<include name="p21"/>
<include name="p3"/>
<exclude name="p31"/>
</packages>
</feature-pack>
</installation>
5. Feature-pack dependencies
Feature-pack may depend on one or more other feature-packs. Feature-pack dependencies are expressed in feature-pack.xml
file. For example:
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
<dependencies>
<dependency location="fp2@maven(org.jboss.universe:community-universe):2#2.0.1"/>
<dependency location="fp3@maven(org.jboss.universe:community-universe):1#1.0.2"/>
</dependencies>
<default-packages>
<package name="package1"/>
<package name="package2"/>
</default-packages>
</feature-pack>
In this case feature-pack fp1
depends on feature-packs fp2
and fp3
. And if a user requests to install fp1
, feature-packs fp2
and fp3
will be installed by the mechanism implicitly as dependencies of fp1
.
If we further assume that fp3
depends on feature-pack fp4
and fp2
and fp4
don’t have any further dependencies. The effective package set of the distribution provisioned from fp1
will consist of:
-
the effective package set of
fp1
; -
the effective package set of
fp2
; -
the effective package set of
fp3
; -
the effective package set of
fp4
.
fp2 and fp3 are called direct dependencies of fp1 , while fp4 is called a transitive dependency of fp1 and a direct dependency of fp3 .
|
5.1. Customizing the effective package set of a dependency
As illustrated in the example above, the effective package set of the dependency contributes to the effective package set of the distribution. The feature-pack declaring the dependency, though, is allowed to customize the effective package set of the dependency (the package set it inherits) using the already mentioned in previous chapters include
and exclude
XML elements in its feature-pack.xml
. For example:
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
<dependencies>
<dependency location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0">
<packages>
<exclude name="p1"/>
<exclude name="p2"/>
<include name="p3"/>
<include name="p4"/>
</packages>
</dependency>
</dependencies>
<default-packages>
<package name="p1"/>
<package name="p2"/>
</default-packages>
</feature-pack>
Element packages
under dependency
in feature-pack.xml
has exactly the same structure as element packages
in the provisioning XML configuration file, mentioned earlier in the chaper describing the effective package set of a feature-pack.
Now the effective package set of a distribution provisioned from fp1
becomes:
-
fp1
packagesp1
andp2
;-
plus their dependencies on non-default packages (if any);
-
-
the effective package set of
fp2
;-
minus packages
p1
andp2
fromfp2
and their dependencies on other packages; -
plus packages
p3
andp4
fromfp2
and their dependencies on other packages.
-
in case fp2 in its turn depended on other feature-packs then the effective package sets of those feature-packs (possibly customized using include /exclude in the corresponding dependency declaration in the feature-pack.xml of fp2 ).
|
5.2. Disabling package inheritance from a dependency
The effective package set of a dependency is inherited by the feature-pack declaring the dependency. However, it is possible to declare the dependency without inheriting its default effective package set and simply pick the desired packages explicitly under dependency
element (in other words, explicitly define the desired effective package set of the dependency).
Optional boolean attribute inherit
of element packages
controls whether package inheritance is enabled or disabled. In case the attribute is not explicitly specified, its value is assumed to be true. Here is an example of a dependency with disabled package inheritance:
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
<dependencies>
<dependency location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0">
<packages inherit=”false”>
<exclude name="p1"/>
<exclude name="p2"/>
<include name="p3"/>
<include name="p4"/>
</packages>
</dependency>
</dependencies>
<default-packages>
<package name="p1"/>
<package name="p2"/>
</default-packages>
</feature-pack>
The exclude elements may at first look redundant, given that package inheritance was disabled in the first place. However, it’s important to keep in mind that when a package is included, by default, all its dependencies are also included. exclude elements can be used to exclude certain transitive dependencies of the included dependencies.
|
Now the effective package set of the distribution provisioned from fp1
becomes:
-
fp1
packagesp1
andp2
;-
plus their dependencies on non-default packages (if any);
-
-
fp2
packagesp3
andp4
;-
plus their dependencies on non-default packages minus packages
p1
andp2
fromfp2
and their dependencies on other packages.
-
5.3. Merging package sets of dependencies
Suppose feature-pack fp1
depends on feature-packs fp2
and fp3
. Both fp2
and fp3
depend on their own custom package sets of feature-pack fp4
. When fp1
is installed, the effective package set of fp4 will be a merge of the custom package sets of fp4
defined in fp2
and fp3
as their dependencies.
For example:
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
<dependencies>
<dependency location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0"/>
<dependency location="fp3@maven(org.jboss.universe:community-universe):2#2.0.0"/>
</dependencies>
<default-packages>
<package name="p1"/>
</default-packages>
</feature-pack>
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0" >
<dependencies>
<dependency location="fp4@maven(org.jboss.universe:community-universe):2#2.0.0">
<packages>
<exclude name="p1"/>
<exclude name="p3"/>
</packages>
</dependency>
</dependencies>
<default-packages>
<package name="p1"/>
</default-packages>
</feature-pack>
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp3@maven(org.jboss.universe:community-universe):2#2.0.0" >
<dependencies>
<dependency location="fp4@maven(org.jboss.universe:community-universe):2#2.0.0">
<packages inherit=”false”>
<!-- assume fp4 also contains non-default package p4 -->
<include name="p4"/>
</packages>
</dependency>
</dependencies>
<default-packages>
<package name="p1"/>
</default-packages>
</feature-pack>
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp4@maven(org.jboss.universe:community-universe):2#2.0.0" >
<default-packages>
<package name="p1"/>
<package name="p2"/>
<package name="p3"/>
</default-packages>
</feature-pack>
A distribution provisioned from fp1
without further customizations will include:
-
fp1:p1
and its dependencies; -
fp2:p1
and its dependencies; -
fp3:p1
and its dependencies; -
fp4:p2
,fp4:p4
and their dependencies.
6. Feature-pack transitive dependencies
Suppose there is feature-pack fp1
that depends on fp2
and fp2
in its turn depends on fp3
. In this case, fp2
is a direct dependency of fp1
while fp3
is a transitive dependency of fp1
and a direct dependency of fp2
.
Transitive dependencies are the dependencies of the dependencies. |
6.1. Customizing package set of a transitive dependency
Let’s suppose we have the following two feature-packs:
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
<dependencies>
<dependency location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0">
<packages inherit="false"> (1)
<include name="p3"/>
<include name="p4"/>
<exclude name="p5"/>
</packages>
</dependency>
</dependencies>
<default-packages>
<package name="p1"/>
</default-packages>
</feature-pack>
1 | Let’s assume fp2 also contains packages p4 , p5 among others. |
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0" >
<default-packages>
<package name="p1"/>
<package name="p2"/>
<package name="p3"/>
</default-packages>
</feature-pack>
If we provision a distribution from fp1
like this
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
</installation>
its effective package set will include:
-
fp1:p1
plus its dependencies; -
p3
andp4
fromfp2
plus their dependencies excludingp5
.
The provisioning mechanism will not install the default configuration of fp2 but its customized version defined by fp1 , in other words a subset of fp2 that fp1 needs.
|
Now if we provision our distribution as
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<feature-pack location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0"/>
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
</installation>
its effective package set will become:
-
fp1:p1
plus its dependencies; -
p1
,p2
,p3
andp4
fromfp2
plus their dependencies (not excludingp5
).
The provisioning mechanism will install the default configuration of fp2 plus what fp1 needs on top of it.
|
feature-pack element appearing in the provisioning configuration under installation always points to the default configuration of the feature-pack.
|
Now let’s suppose we want to add another package from fp2
to our distribution but we want to start from the customized fp2
configuration defined by fp1
. One way of achieving that would be
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<feature-pack location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0">
<packages inherit="false">
<include name="p3"/>
<include name="p4"/>
<exclude name="p5"/>
<include name="p6"/> (1)
</packages>
</feature-pack>
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
</installation>
1 | the package we want to add to our distribution |
That works but is not very practical. We basically copied the customizations of fp2
from fp1
to our provisioning configuration. If the configuration was more sophisticated it wouldn’t be that easy. Here is an easier alternative:
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<transitive>
<feature-pack location="fp2@maven(org.jboss.universe:community-universe)"> (1)
<packages>
<include name="p6"/>
</packages>
</feature-pack>
</transitive>
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
</installation>
1 | Note, although we could provide the full version of fp2 here, we chose not to, the mechanism will resolve it to the version specified in feature-pack.xml of fp1 |
By including feature-pack element under transitive we indicate to the provisioning mechanism that the feature-pack we are about to customize appears on a dependency branch of another feature-pack installed in this configuration directly and that we want to adjust the configuration defined by the feature-pack that depends on it instead of the configuration defined in its feature-pack.xml .
|
7. Dependency version convergence
This chapter describes how Galleon picks the version of a dependency to install when multiple versions of that dependency appear on the installation’s dependency tree.
The first rule is: versions specified in the provisioning configuration of the installation, e.g. provisioning.xml , for direct or transitive feature-pack dependencies, represent the user’s choice and are always installed, even if the dependency hierarchy of the installation includes other versions of those feature-packs.
|
Suppose we have these feature-packs
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
<dependencies>
<dependency location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0"/>
</dependencies>
<default-packages>
<package name="p1"/>
</default-packages>
</feature-pack>
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0" >
<default-packages>
<package name="p1"/>
</default-packages>
</feature-pack>
Feature-pack fp1
declares a dependency on version 2.0.0
of fp2
. Even if later backward compatible versions of fp2
are available, provisioning a distribution from fp1
will get fp2
version 2.0.0
installed. If we still want to upgrade fp2
there are two ways to do that
1) install the desired version of fp2
directly as
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<feature-pack location="fp2@maven(org.jboss.universe:community-universe):2#2.0.1"/>
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
</installation>
2) use transitive
element to override the version of fp2
specified in feature-pack.xml
of fp1
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<transitive>
<feature-pack location="fp2@maven(org.jboss.universe:community-universe):2#2.0.1"/>
</transitive>
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
</installation>
The advantage of specifying the version in the transitive dependency is that it will override only the version of fp2
w/o affecting its customizations (if any) applied to fp2
by fp1
. While installing the new version directly will install the default configuration of fp2
.
Feature-pack versions that appear higher in the feature-pack dependency hierarchy (i.e. closer to the root in the provisioning configuration) override the versions that appear further down in the dependency hierarchy, no matter whether they are higher or lower in comparison. |
7.1. Version convergence of dependency branches
It is possible to run into a version conflict when feature-packs on different dependency branches delcare dependencies on different versions of the same feature-pack. Here is an example
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0" >
<dependencies>
<dependency location="fp3@maven(org.jboss.universe:community-universe):1#1.2.0"/>
</dependencies>
<default-packages>
<package name="p1"/>
</default-packages>
</feature-pack>
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0" >
<dependencies>
<dependency location="fp3@maven(org.jboss.universe:community-universe):1#1.3.0"/>
</dependencies>
<default-packages>
<package name="p1"/>
</default-packages>
</feature-pack>
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
<feature-pack location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0"/>
</installation>
In this case, Galleon will pick version 1.2.0
of fp3
simply because it was processed first as the dependency of fp1
.
By default Galleon will pick the first processed feature-pack version even if other feature-packs of the installation depend on a newer compatible version of the feature-pack from the same channel. |
This behaviour may change in the future in favor of picking the latest compatible version of the feature-pack. |
In the example above both fp1 and fp2 depend on the same channel of fp3 . If they depended on different channels of fp3 , the provisioning would fail because different channels represent different compatibilty streams.
|
The user can also resolve this kind of version conflict by either installing fp3
directly or specifying its desired version in the transitive
element of the installation
. E.g.
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<transitive>
<feature-pack location="fp3@maven(org.jboss.universe:community-universe):1#1.4.0"/>
</transitive>
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0"/>
<feature-pack location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0"/>
</installation>
7.2. Disabling version convergence
There is a provisioning property called version-convergence
which can be set to fail
to disable the dependency version convergence that happens when merging dependency branches.
Even if version-convergence is set to fail , feature-pack versions that appear higher in the feature-pack dependency hierarchy (i.e. closer to the root in the provisioning configuration) will still override the versions that appear further down in the dependency hierarchy, no matter whether they are higher or lower in comparison.
|
8. Generic configuration model
In addition to provisioning various filesystem content as packages, the mechanism also allows generation of the configuration files for the target installation taking into account the customizations applied by the user to the feature-pack defaults.
Feature-pack may include predefined configurations for the installation. They are stored in feature-pack’s configs
directory. Every configuration is described in an XML file and in a simple (and perhaps the most common) case, every configuration will represent a specific configuration file in the provisioned installation.
Feature-pack metadata (feature-pack.xml
) may define which of the predefined configurations should be provisioned by default by referencing them using config
elements .
Installation configuration is described using a generic configuration model. The generic configuration model is based on an abstract schema that describes configurable units and relationships between them. The model allows a user to manipulate the confguration in a generic way by adding to and/or removing parts from it, and/or overwriting some parameter values. The responsibilities of the core provisioning mechanism with regards to the configuration are:
-
resolve the final installation configuration model taking into account the customizations applied to the pre-defined in
feature-pack.xml
default configuration; -
make sure the resolved configuration model is valid by:
-
verifying that all the required parameter values are set;
-
checking the referential integrity of the resolved configuration model (i.e. in case certain configuration units imply presence of certain other configuration units);
-
making sure that the capability requirements in the resolved configuration are satisfied;
-
and that packages required by the configuration model are included into the installation;
-
-
present the units of the resolved configuration to the provisioning plugins in the order the configuration model was populated but also respecting the dependencies of those units.
The generic provisioning mechanism itself does not generate the final configuration files. As indicated above, it only resolves the effective generic configuration model for the provisioned installation and makes sure it does not violate various constraints it might have. It is the responsibility of product-specific provisioning plugins to generate the final configuration file(s) from the already resolved and validated generic configuration model. |
8.1. Features
Minimal configurable unit of the generic configuration model is called a feature. A feature is described by a feature specification (or feature spec further in the text). A feature spec describes how a feature can be configured, while a feature is a specific configuration of a feature spec.
Feature specs are identified by their names that must be unique in the scope of the feature-pack.
A feature spec describes
-
the configurable parameters (including their names, default values (if any) and whether they are nillable);
-
(optionally) references to other feature specs;
-
(optionally) dependencies on other features;
-
(optionally) required capabilities;
-
(optionally) provided capabilities;
-
(optionally) dependencies on packages;
-
(optionally) annnotations.
Feature specs are stored in spec.xml
files in the directories named after the feature spec names under feature-pack’s features
directory. For example
features/ |-feature1/ | `-spec.xml `-feature2/ `-spec.xml
8.1.1. Feature ID
A feature may have an identifier (feature id further in the text) which is used to locate a specific feature in the configuration model. Whether a feature has an ID or not is specified in the feature spec.
A feature ID is essential to be able to customize the configuration of a specific feature. |
Feature ID consists of a feature spec name plus one or more feature parameters. Feature parameters that are a part of the feature ID include feature-id="true"
attribute in their descriptions (and cannot be nillable). For example
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="feature1">
<params>
<param name="name" feature-id="true"/>
<param name="b" default="bb"/>
<param name="c" nillable="true"/>
</params>
</feature-spec>
Now if a config includes multiple features of feature spec feature1
, they could be refered to by feature1:name=unique_name expression, where unique_name is the value of parameter name
of the target feature.
Feature ID parameters cannot change values during config customizations. If a user wants to have a different value for an ID parameter of a certain feature, the existing feature has to be excluded from the config and a new feature with the desired ID parameter value has to be added in. |
Here is an example of a feature spec with multiple feature ID parameters:
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="feature2">
<params>
<param name="p1" feature-id="true"/>
<param name="p2" feature-id="true"/>
<param name="p3" nillable="true"/>
</params>
</feature-spec>
An ID of a feature of this spec will look like feature2:p1=p1_value,p2=p2_value.
The order of the ID parameters in the feature ID string is not significant. |
8.1.2. Feature parameters
Feature parameters are described in feature specs. A parameter is identified by its name (which must be unique in the scope of the feature spec) and may have the following attributes:
-
required string name - the name of the parameter;
-
optional boolean feature-id - indicating whether the parameter is a part of the feature ID (if not present, the default is assumed to be false);
-
optional boolean nillable - indicating whether the parameter allows null as the value in the resolved config (if not present, the default is assumed to be false);
-
optional string default - indicates which value should be used for the parameter, if the parameter was not explicitly initialized in the configuration (if not present, the default is assumed to be null);
-
optional string type - type of the parameter (if not present, the default is assumed to be String).
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="feature1">
<params>
<param name="a" feature-id="true"/> (1)
<param name="b" default="bb"/> (2)
<param name="c" nillable="true"/> (3)
<param name="d"/> (4)
</params>
</feature-spec>
1 | feature ID parameter, cannot be null and must be explicitly initialized in the configuration |
2 | parameter will be initialized to bb unless explicitly set to a different value by the user; |
3 | has no default and may be left uninitialized in the configuration; |
4 | parameter must be explicitly initialized by the user. |
8.1.3. Features in configuration
Here is an example of how features can be used in a configuration.
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
<config name="main">
<feature spec="feature1">
<param name="a" value="a1"/>
<param name="b" value="b1"/>
<param name="d" value="d1"/>
</feature>
<feature spec="feature1">
<param name="a" value="a2"/>
<param name="d" value="d2"/>
</feature>
<feature spec="feature1">
<param name="a" value="a3"/>
<param name="c" value="c3"/>
<param name="d" value="d3"/>
</feature>
</config>
</feature-pack>
In this example, the config
element describes the default configuration which will be generated when fp1
is installed (unless it is explicitly customized by the user), which includes three features of the same spec. When the final configuration is generated, the features will be processed in the order they appear in the config
element.
8.1.4. Feature references
There are cases when a value range of a parameter of one feature spec is defined by a set of existing in the configuration model values of an ID parameter of another feature spec. In other words, a feature spec may declare certain parameters as references to ID parameters of another feature spec. (In a relational database, this would be a foreign key reference).
In a feature spec a simple feature reference would look like this
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
<refs>
<ref feature="featureP"/>
</refs>
<params>
<param name="name" feature-id="true"/>
<param name="p"/>
</params>
</feature-spec>
Attribute feature
of element ref
contains the name of the referenced feature-spec. Note that we have not provided which parameter of featureC
references the ID parameter of featureP
. This example also demonstrates the default (implicit) reference parameter mapping.
The default reference parameter mapping rule is based on the expectation that the feature spec declaring the reference includes parameters with the names matching the ID parameter names of the referenced feature spec. |
So the example above will work if one of the following statements is true:
-
featureP
declares parameterp
and it is its only feature-id parameter; -
featureP
declares parametername
and it is its only feature-id parameter; -
featureP
declares parametersname
andp
as its feature-id parameters and has not other feature-id parameters.
Attribute name | Required | Default | Description |
---|---|---|---|
dependency |
false |
null (current feature-pack or its dependencies) |
The feature-pack dependency name the referenced feature spec belongs to. |
feature |
true |
null |
The name of the referenced feature spec. |
name |
false |
The value of the feature attribute |
Unique feature reference name. |
nillable |
false |
false |
Whether a reference is nillable or not. |
include |
false |
false |
Whether the referenced feature should automatically be included into the config model if it was not explicitly configured. |
Non-default reference parameter mapping
Instead of relying on the default reference parameter mapping rule, it is also possible to map the parameters in the reference declaration explicitly. The example below will correspond to the statement 1. from the example above.
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
<refs>
<ref feature="featureP">
<param name="p" maps-to="p"/>
</ref>
</refs>
<params>
<param name="name" feature-id="true"/>
<param name="p"/>
</params>
</feature-spec>
Now let’s suppose that featureP
ID parameter is in fact name
but we still want to use parameter p
as the reference to featureP
.
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
<refs>
<ref feature="featureP">
<param name="p" maps-to="name"/>
</ref>
</refs>
<params>
<param name="name" feature-id="true"/>
<param name="p"/>
</params>
</feature-spec>
If featureP
had more than one ID parameter, e.g.
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureP">
<params>
<param name="id1" feature-id="true"/>
<param name="id2" feature-id="true"/>
</params>
</feature-spec>
Then the reference parameter mapping in featureC
could look like:
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
<refs>
<ref feature="featureP">
<param name="p1" maps-to="id1"/>
<param name="p2" maps-to="id2"/>
</ref>
</refs>
<params>
<param name="name" feature-id="true"/>
<param name="p1"/>
<param name="p2"/>
</params>
</feature-spec>
Nillable feature references
Feature reference resolves to null if one of the feature reference parameters is null. |
If a reference resolves to null and its not marked as nillable in the feature spec, the provisioning will fail with an error. Here is an example of a nillable reference declaration: |
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
<refs>
<ref feature="featureP" nillable="true">
<param name="p1" maps-to="id1"/>
<param name="p2" maps-to="id2"/>
</ref>
</refs>
<params>
<param name="name" feature-id="true"/>
<param name="p1" nillable="true"/>
<param name="p2"/>
</params>
</feature-spec>
External feature references
A feature may reference a feature from another feature-pack. The other feature-pack must be a (direct or transitive) dependency of the feature-pack the referencing feature belongs to.
Unless the feature-pack of the referenced feature has not been explicitly specified, the mechanism will navigate the dependency tree of the feature-pack of the referencing feature and the first feature-pack containing a feature spec with the referenced feature spec name will be selected as the target. |
Otherwise, the target feature-pack can be specified using dependency
attribute of the feature reference declaration. The value of dependency
attribute must match the value of origin
element of the feature-pack dependency (the referenced feature spec belongs to) declaration in the feature-pack.xml
file of the referencing feature spec.
For example, suppose, feature-pack fp1
depends on feature-pack fp2
.
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
<dependencies>
<dependency location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0">
<origin>fp2-dep</origin>
</dependency>
</dependencies>
</feature-pack>
fp2
includes feature spec featureP
.
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureP">
<params>
<param name="p" feature-id="true"/>
</params>
</feature-spec>
And fp1
includes feature spec featureC
which declares a reference to featureP
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
<refs>
<ref dependency="fp2-dep" feature="featureP"/>
</refs>
<params>
<param name="name" feature-id="true"/>
<param name="p"/>
</params>
</feature-spec>
It is expected that in most cases dependency attribute of element ref will not have to be used.
|
Implicit feature reference parameter initialization
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureP">
<params>
<param name="parentId" feature-id="true"/>
</params>
</feature-spec>
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
<refs>
<ref feature="featureP"/>
</refs>
<params>
<param name="childId" feature-id="true"/>
<param name="parentId"/>
</params>
</feature-spec>
If we were to add features of these specs to a config, it could look like this
<config name="main">
<feature spec="featureP">
<param name="parentId" value="parent1"/>
</feature>
<feature spec="featureC">
<param name="childId" value="child1"/>
<param name="parentId" value="parent1"/>
</feature>
</config>
This approach is very verbose, the value for parentId
parameter is set on every feature. There is a more compact way of expressing the same configuration using nesting, e.g.
<config name="main">
<feature spec="featureP">
<param name="parentId" value="parent1"/>
<feature spec="featureC">
<param name="childId" value="child1"/>
</feature>
</feature>
</config>
Here, parentId
parameter is initialized only once for the parent feature. parentId
of the child feature will be implicitly initialized to the value of parentId
of the parent.
When a feature is nested, the tool will look in the feature spec of the nested feature for a reference declaration with the name matching the outer feature spec and, if it is found, the tool will resolve the reference parameter mappings and will initialize the parameters of the child feature referencing the parent. |
In case the reference name is different from the referenced feature spec name, i.e. it was explicitly set in the reference spec, e.g.
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
<refs>
<ref feature="featureP" name="parent"/>
</refs>
<params>
<param name="childId" feature-id="true"/>
<param name="parentId"/>
</params>
</feature-spec>
Then the name of the reference has to be explicitly specified when the child feature is nested using the parent-ref
attribute, e.g.
<config name="main">
<feature spec="featureP">
<param name="parentId" value="parent1"/>
<feature spec="featureC" parent-ref="parent">
<param name="childId" value="child1"/>
</feature>
</feature>
</config>
it is also possible to include a feature-group as a child of the feature. |
Implicit inclusion of referenced features into the configuration
It is possible to configure feature references so that when the resolved referenced feature ID is not found in the configuration model, instead of failing with the referential integrity constraint error, implicitly include the referenced feature into the configuration model initializing it with its default values. This is done by simply setting include
attribute of the feature reference declaration to true
.
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
<refs>
<ref dependency="fp2-dep" feature="featureP" include="true"/>
</refs>
<params>
<param name="name" feature-id="true"/>
<param name="p"/>
</params>
</feature-spec>
Multiple references to the same feature spec
Suppose a feature needs to declare more than one reference to the same feature spec. For example let’s model a chain using a feature spec called link
. link
must have an ID parameter, let’s call it id
. Then it has to include a parameter to reference the previous link and another parameter to reference the next link in the chain. The following, although looking right from the parameter mapping perspective, will clearly not work
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="link">
<refs>
<ref feature="link">
<param name="prev-id" maps-to="id"/>
</ref>
<ref feature="link">
<param name="next-id" maps-to="id"/>
</ref>
</refs>
<params>
<param name="id" feature-id="true"/>
<param name="prev-id" nillable="true"/>
<param name="next-id" nillable="true"/>
</params>
</feature-spec>
Feature references must have a unique name. In this case, both reference names are set to link and the provisioning tool will fail to process this spec. To workaround the error explicit names have to be assigned to the reference declarations, e.g.
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="link">
<refs>
<ref name="prev" feature="link">
<param name="prev-id" maps-to="id"/>
</ref>
<ref name="next" feature="link">
<param name="next-id" maps-to="id"/>
</ref>
</refs>
<params>
<param name="id" feature-id="true"/>
<param name="prev-id" nillable="true"/>
<param name="next-id" nillable="true"/>
</params>
</feature-spec>
Processing of features with references
One of the responsibilities of the provisioning tool is to order the features from the resolved configuration model for processing by the provisioning plugins that generate the final installation configuration files. While the general rule is to preserve the order in which the features where added to the configuration model, when feature A
references feature B
, feature B
will get the priority and will be processed by the provisioning plugins before feature A
to not break the referential integrity of the generated model (if it is significant for the consuming plugin).
Circular feature references
The provisioning mechanism is capable of identifying circular references (circular reference graphs). It does not throw an error if a circular reference graphs is detected. The responsibility of the provisioning mechanism is to make sure the configuration model is valid and all the referential integrity constraints are satisfied. From this point of view circular references are not illegal.
The issue with circular references is the ordering of the features when configuration model is processed by the product specific plugins that generate the final configuration files. In some cases the order of the features will not be significant but in some cases it will be. So the rule is
When a circular reference graph is identified, the feature that was added to the configuration model first will be processed by the provisioning plugins first, the rest of the features from the graph will be processed respecting the references as usual. |
8.1.5. Feature dependencies
While references are a kind of dependencies, they require parameters in the spec of the feature declaring the reference to identify the target. Unlike references, feature dependencies do not use parameters to specify the target. Instead the dependency is declared by specifying the ID of the target feature directly.
Feature spec dependencies
Feature dependencies can be declared in the feature spec and/or on the feature itself. Here is an example of a dependency declaration in the feature spec:
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="feature1">
<deps>
<dep feature-id="feature2:id=123"/>
</deps>
<params>
<param name="name" feature-id="true"/>
</params>
</feature-spec>
Now all the features of spec feature1
will depend on the feature with ID feature2:id=123
.
Feature config dependencies
And here is how a feature dependency can be declared on a specific feature:
<feature spec="feature1">
<deps>
<dep feature-id="feature3:id=789"/>
</deps>
<param name="name" value="abc"/>
</feature>
Now feature feature1:name=abc
depends on feature feature2:id=123
(inherited dependency from the spec) and feature feature3:id=789
.
External feature dependencies
It is allowed to delcalre dependencies on features that come from other feature-packs. If the specs of those features come from feature-packs that appear to be dependencies of the feature-pack the feature dependencies are configured in then those feature specs will most probably be located by the mechanism automatically (by navigating the feature-pack dependency tree). The mechanism might need some help resolving the specs of the dependencies only if they belong to a feature-pack that doesn’t appear to be a dependency of the feature-pack where the dependencies are defined or if there are multiple feature specs with the same name in the feature-pack dependency hierarchy and it’s not obvious which one is targeted by the dependency.
the feature spec resolution mechanism will pick the first feature spec with the matching name met while navigating the feature-pack dependency tree. |
There is a way though to specify the origin of the feature spec used in the dependency. If feature3
spec was from another feature-pack than feature1
spec then to be precise we could have added the origin of feature3
spec to the dependency declaration. Assuming that the feature-pack feature1
spec belongs to declared a dependecy named fp2
on the feature-pack feature3
spec belongs to, the dependency declaration would look like this:
<feature spec="feature1">
<deps>
<dep feature-id="feature3:id=789" dependency="fp2"/>
</deps>
<param name="name" value="abc"/>
</feature>
Implicit inclusion of feature dependencies
Like references, dependencies also support include
attribute. If the dependency is declared with include=true
, the target of the dependency will implicitly be included into the configuration unless it is already present. Here is an example of an implicitly included feature dependency:
<feature spec="feature1">
<deps>
<dep feature-id="feature3:id=789" include="true"/>
</deps>
<param name="name" value="abc"/>
</feature>
8.1.6. Feature capabilities
In the actual provisioned installation, the components that are represented as features in the configuration model may provide certain runtime capabilities that other components, also represented as features in the configuration model, may depend upon. There are two reasons why this may be important when resolving the configuration model for the installation to be provisioned:
-
to make sure the configuration is consistent in a sense that the runtime requirements of its components are satisfied;
-
to order the features in the configuration model for processing by the provisioning plugins based on their dependencies and runtime requirements.
Capabilities are represented as strings with a dot serving as a word separator. Here is an example of a feature spec providing a capability:
<feature-spec name="interface" xmlns="urn:jboss:galleon:feature-spec:1.0">
<provides>
<capability name="org.wildfly.network.interface"/>
</provides>
<params>
<param name="name" feature-id="true"/>
<param name="inet-address"/>
</params>
</feature-spec>
And here is a feature spec that requires the capability provided above
<feature-spec name="socket-binding" xmlns="urn:jboss:galleon:feature-spec:1.0">
<requires>
<capability name="org.wildfly.network.interface"/>
</requires>
<params>
<param name="name" feature-id="true"/>
<param name="port"/>
</params>
</feature-spec>
In the examples above the capabilities were configured using constant values. This type of a capability is called a static capability. As a consequence, all the features of spec interface will provide the same capability org.wildfly.network.interface . And all the features of spec socket-binding will require the same capabality org.wildfly.network.interface .
|
Dynamic capabilities
It is also possible, however, to provide and/or require a capability that depends on the parameters of a specific feature. Dynamic capabilities are following the same dot-separated string format but include feature parameter names prefixed with $
character. The examples above could be enhanced with dynamic capabilities as
<feature-spec name="interface" xmlns="urn:jboss:galleon:feature-spec:1.0">
<provides>
<capability name="org.wildfly.network.interface.$name"/>
</provides>
<params>
<param name="name" feature-id="true"/>
<param name="inet-address" nillable="true"/>
</params>
</feature-spec>
<feature-spec name="socket-binding" xmlns="urn:jboss:galleon:feature-spec:1.0">
<requires>
<capability name="org.wildfly.network.interface.$interface"/>
</requires>
<params>
<param name="name" feature-id="true"/>
<param name="interface"/>
<param name="port" nillable="true"/>
</params>
</feature-spec>
Let’s see how it will look like in an actual configuration
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
<config name="main">
<feature spec="interface">
<param name="name" value="public"/>
</feature>
<feature spec="interface">
<param name="name" value="secure"/>
</feature>
<feature spec="socket-binding">
<param name="name" value="http"/>
<param name="interface" value="public"/>
</feature>
<feature spec="socket-binding">
<param name="name" value="https"/>
<param name="interface" value="secure"/>
</feature>
</config>
</feature-pack>
In the example above feature interface:name=public
provides capability org.wildfly.network.interface.public
which is required by feature socket-binding:name=http
. And feature interface:name=secure
provides capability org.wildfly.network.interface.secure
which is required by feature socket-binding:name=https
.
More than one parameter could be used in a capability name. The parameters may appear in any part of the name, not necessarily at the end as in the example. The only rule is to use dot as a separator for the parameters and the static parts of the name. |
Optional capabilities
In the example above, parameter interface
in both feature specs is not nillable, which means the capability will always be provided by interface
and always be required socket-binding
. There could be cases though, when a parameter referenced from the capability name is nillable. In fact, if the parameter is null, the capability name will fail to resolve and provisioning will fail. However, dynamic capabilities can be marked as optional. Optional dynamic capability will be provided (or required) only if its name could be resolved (i.e. all the parameters referenced were not null). Here is the example illustrating optional capabilities in a feature spec:
<feature-spec name="specA" xmlns="urn:jboss:galleon:feature-spec:1.0">
<provides>
<capability name="$b" optional="true"/>
</provides>
<requires>
<capability name="$c" optional="true"/>
</requires>
<params>
<param name="id" feature-id="true"/>
<param name="b" nillable="true"/>
<param name="c" nillable="true"/>
</params>
</feature-spec>
8.1.7. Feature package dependencies
Feature specs representing configurable components of the installation may include dependencies on feature-pack packages that contain certain binary content (e.g. JAR files) of those installation components. So that, when a feature is included into configuration, the packages the feature will require at runtime will automatically be added to the list of the installed packages.
Package dependencies are configured under packages
element of the feature spec which is equivalent to the dependencies
element of the package spec metadata. Here is an example
<feature-spec name="feature1" xmlns="urn:jboss:galleon:feature-spec:1.0">
<params>
<param name="id" feature-id="true"/>
</params>
<packages>
<package name="p1"/>
<package name="p2" optional="true"/>
<origin name="another-feature-pack">
<package name="p2"/>
<package name="p3" optional="true"/>
</origin>
</packages>
</feature-spec>
In this case, any feature of spec feature1
will have:
-
a required dependency on package
p1
; -
an optional dependency on package
p2
; -
a required dependency on package
p2
from the feature-pack dependency refered to asanother-feature-pack
; -
an optional dependency on package
p3
from the feature-pack dependency refered to asanother-feature-pack
.
8.1.8. Feature annotations
Feature specs may include a list of annotations. The provisioning mechanism includes a few pre-defined annotations. Product-specific annotations are also supported, they are simply parsed and attached to feature specs and are available to the provisioning plugins for processing. Here is an example of an annotated feature spec:
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="feature1">
<annotation name="name1">
<elem name="elem1" value="value1"/>
</annotation>
<annotation name="name2">
<elem name="elem1" value="value1"/>
<elem name="elem1" value="value1"/>
</annotation>
<params>
<param name="id" feature-id="true"/>
</params>
</feature-spec>
8.2. Feature groups
A feature spec represents a minimal configuration unit. When a configuration model reaches a certain level of complexity though, using and manipulating features to define the final configuration may become impractical. Feature groups allow to group a set of features that represent a certain part of the configuration together and then include them all into the final configuration as a group. For example
<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">
<feature spec="feature1">
<param name="id" value="a1"/>
<feature spec="feature2">
<param name="id" value="b1"/>
</feature>
</feature>
<feature spec="feature3">
<param name="id" value="c1"/>
</feature>
</feature-group-spec>
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
<config name="main">
<feature-group name="group1"/>
</config>
</feature-pack>
First, we defined a feature group named group1
which includes three features.
The name of the group must be unique in the scope of the feature-pack. |
Feature groups are saved in the feature-pack’s feature_groups
directory in XML files named after the feature groups (group1.xml
in this example).
Then in the default configuration of the feature-pack we simply included group1
, which is equivalent to including the mentioned three features into the config directly.
Besides features, feature groups may also include other feature groups. Continuing the example above:
<feature-group-spec name="group2" xmlns="urn:jboss:galleon:feature-group:1.0">
<feature-group name="group1"/>
<feature spec="feature4">
<param name="id" value="d1"/>
</feature>
</feature-group-spec>
<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
<config name="main">
<feature-group name="group2"/>
</config>
</feature-pack>
The final configuration will now include all the four features.
The order of the features in the resolved configuration will reflect the order in which the features were included into the configuration but also respecting the feature references and the dependencies, i.e. |
-
feature1:id=a1
-
feature2:id=b1
-
feature3:id=c1
-
feature4:id=d1
8.2.1. Including customized feature groups
When a feature group is included (into another feature group or a config
element of a feature-pack configuration) the set of its features can be customized. There are two main kinds of customizations that are allowed when including a feature group:
-
the configuration of the features included into the group can be overwritten;
-
certain features can be excluded from the group by
When a feature group is included into another feature group or a config element, the list of its direct entries (features and feature groups) defined by the feature group spec cannot be extended by applying customizations. There is a way though to extend the feature set of the included feature group indirectly.
|
All the feature group customizations are expressed in the body of feature-group
XML element.
Overwriting parameters of features from a feature group
The configuration of a feature can be customized by adding include
element with feature-id
attribute targeting its ID to the body of the feature-group
element. E.g. suppose this is our feature spec:
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="feature1">
<params>
<param name="a" feature-id="true"/>
<param name="b" default="bb"/>
<param name="c" nillable="true"/>
<param name="d"/>
</params>
</feature-spec>
This is our feature group spec:
<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">
<feature spec="feature1">
<param name="a" value="a1"/>
<param name="c" value="group1"/>
<param name="d" value="group1"/>
</feature>
</feature-group-spec>
And this is our config:
<config name="main">
<feature-group name="group1">
<include feature-id="feature1:a=a1">
<param name="d" value="config"/>
</include>
</feature-group>
</config>
The resolved configuration will consist of one feature with the following configuration
Feature spec | a | b | c | d |
---|---|---|---|---|
feature1 |
a1 |
bb |
group1 |
config |
Let’s now suppose that we have two feature specs with a parent-child relationship
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureP">
<params>
<param name="parent" feature-id="true"/>
</params>
</feature-spec>
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
<refs>
<ref feature="featureP">
</refs>
<params>
<param name="parent" feature-id="true"/>
<param name="child" feature-id="true"/>
<param name="a"/>
<param name="b"/>
</params>
</feature-spec>
The group is defined as
<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">
<feature spec="featureP">
<param name="parent" value="p1"/>
<feature spec="featureC">
<param name="child" value="c1"/>
<param name="a" value="group1"/>
<param name="b" value="group1"/>
</feature>
</feature>
</feature-group-spec>
And we want to customize the child feature when including group1
into the config.
<config name="main">
<feature-group name="group1">
<include feature-id="featureC:parent=p1,child=c1">
<param name="b" value="config"/>
</include>
</feature-group>
</config>
The resolved configuration will contain two features:
Feature spec | parent |
---|---|
featureP |
p1 |
Feature spec | child | a | b |
---|---|---|---|
featureC |
p1 |
c1 |
group1 |
Excluding features from a group by IDs
When a feature group is included into another group or a config, certain features can be excluded from the included feature set by simply specifying their IDs.
Suppose, we have defined the following group:
<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">
<feature spec="feature1">
<param name="id" value="a1"/>
</feature>
<feature spec="feature1">
<param name="id" value="a2"/>
</feature>
<feature spec="feature2">
<param name="id" value="b1"/>
</feature>
<feature spec="feature2">
<param name="id" value="b2"/>
</feature>
</feature-group-spec>
Here is how feature1:id=a1
and feature2:id=b1
can be excluded when group1
is added a configuration:
<config name="main">
<feature-group name="group1">
<exclude feature-id="feature1:id=a1"/>
<exclude feature-id="feature2:id=b1"/>
</feature-group>
</config>
The config will include feature1:id=a2
and feature2:id=b2
.
Excluding features from a group by specs
When a feature group is included into another group or a config, all the features of a specific feature spec can be excluded from the included feature set by simply specifying the feature spec.
Suppose, we have the following group spec:
<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">
<feature spec="feature1">
<param name="id" value="a1"/>
</feature>
<feature spec="feature1">
<param name="id" value="a2"/>
</feature>
<feature spec="feature2">
<param name="id" value="b1"/>
</feature>
<feature spec="feature2">
<param name="id" value="b2"/>
</feature>
</feature-group-spec>
Here is how all the feature of spec feature1
can be excluded:
<config name="main">
<feature-group name="group1">
<exclude spec="feature1"/>
</feature-group>
</config>
The config will include feature2:id=b1
and feature2:id=b2
.
Picking features from a group by IDs
When a feature group is included into another feature group or a config, by default all the features it contains are included into the configuration. It is possible though to pick which ones exactly should be included.
Suppose, we have the following group spec:
<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">
<feature spec="feature1">
<param name="id" value="a1"/>
</feature>
<feature spec="feature1">
<param name="id" value="a2"/>
</feature>
<feature spec="feature2">
<param name="id" value="b1"/>
</feature>
<feature spec="feature2">
<param name="id" value="b2"/>
</feature>
</feature-group-spec>
Here is how feature1:id=a1
and feature2:id=b1
can be picked into the configuration:
<config name="main">
<feature-group name="group1" inherit-features="false">
<include feature-id="feature1:id=a1"/>
<include feature-id="feature2:id=b1"/>
</feature-group>
</config>
inherit-features attribute indicates whether the whole feature set of the group should be included into the config or not. If this attribute is not specified, its value is assumed to be true .
|
Then include
elements are picking the features that need to be included into the configuration.
The config will include feature1:id=a1
and feature2:id=b1
.
include elements can also be used to pick features from the excluded feature specs. The config below is equivalent to the config above.
|
<config name="main">
<feature-group name="group1" inherit-features="true">
<exclude spec="feature1"/>
<exclude spec="feature2"/>
<include feature-id="feature1:id=a1"/>
<include feature-id="feature2:id=b1"/>
</feature-group>
</config>
Including features of specific feature specs from a group
When a feature group is included into another group or a config, by default all the features it contains are added to the configuration. There is a way though to pick features of which feature specs should be included.
Suppose, we have the following group spec:
<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">
<feature spec="feature1">
<param name="id" value="a1"/>
</feature>
<feature spec="feature1">
<param name="id" value="a2"/>
</feature>
<feature spec="feature2">
<param name="id" value="b1"/>
</feature>
<feature spec="feature2">
<param name="id" value="b2"/>
</feature>
</feature-group-spec>
Here is how all the features of spec feature1
can be included into the config:
<config name="main">
<feature-group name="group1" inherit-features="false">
<include spec="feature1"/>
</feature-group>
</config>
inherit-features attribute indicates whether the whole feature set of the group should be included into the config or not. If this attribute is not specified, its value is assumed to be true .
|
Then include
element is specifying the feature spec features of which should be included into the config.
The config will include feature1:id=a1
and feature1:id=a2
.
<exclude feature-id="xxx"/> elements can be used to exclude certain features from the feature set of the included feature spec.
|
Extending feature groups by including features indirectly
While the list of the feature group spec enrties (features and feature groups) is fixed and cannot be extended, new features and feature groups can be added as children of the features that have already been included into the feature group. Let’s edit the example from the previous paragraph to demonstrate that. The feature specs will remain the same.
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureP">
<params>
<param name="parent" feature-id="true"/>
</params>
</feature-spec>
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
<refs>
<ref feature="featureP">
</refs>
<params>
<param name="parent" feature-id="true"/>
<param name="child" feature-id="true"/>
<param name="a"/>
<param name="b"/>
</params>
</feature-spec>
The group definition will now include only parent feature
<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">
<feature spec="featureP">
<param name="parent" value="p1"/>
</feature>
</feature-group-spec>
And now we will include the child feature as a configuration customization of the parent feature.
<config name="main">
<feature-group name="group1">
<include feature-id="featureP:parent=p1">
<feature spec="featureC">
<param name="child" value="c1"/>
<param name="a" value="config"/>
<param name="b" value="config"/>
</feature>
</include>
</feature-group>
</config>
The resolved configuration will contain both features:
Feature spec | parent |
---|---|
featureP |
p1 |
Feature spec | parent | child | a | b |
---|---|---|---|---|
featureC |
p1 |
c1 |
config |
config |
8.2.2. Including features and feature groups from other feature-packs
Feature groups, as well as config
elements in feature-pack.xml
, may include features and feature groups from other feature-packs. If those feature-packs appear to be dependencies (direct or transitive) of the feature-pack that uses their feature specs and groups in its configuration, the mechanism will most probably be able to resolve the origins of those feature specs and groups by navigating the feature-pack dependency tree.
However, if there are multiple feature specs or feature groups with the same name in the feature-pack dependency hierarchy, it may become confusing which feature spec or feature group was meant as the target. In this case, the origin of those feature specs and feature groups can be specified with element origin
and its attribute 'name' referencing the corresponding feature-pack dependency declared in the feature-pack.xml
. For example
<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">
<feature spec="feature1">
<param name="id" value="a1"/>
</feature>
<origin name="another-feature-pack">
<feature-group name="group2"/>
<feature spec="feature2">
<param name="id" value="b1"/>
</feature>
</origin>
<feature-group name="group3"/>
<origin name="another-feature-pack">
<feature-group name="group3"/>
</origin>
</feature-group-spec>
In this case, the order of the features in the resolved feature group will be
-
feature1:id=a1
from the local feature-pack; -
features from
group2
fromanother-feature-pack
; -
feature2:id=b1
fromanother-feature-pack
; -
features from
group3
from the local feature-pack; -
features from
group3
fromanother-feature-pack
.
8.2.3. Nesting feature groups under features
It was mentioned in an earlier chapter that a feature may nest other features that reference it. It is also possible to nest a feature group under a feature with the condition that all the features included directly into the definition of the feature group reference the same parent feature.
For example, suppose we have a parent feature spec featureP
and child feature specs featureA
and featureB
:
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureP">
<params>
<param name="parent" feature-id="true"/>
</params>
</feature-spec>
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureA">
<refs>
<ref feature="featureP"/>
</refs>
<params>
<param name="parent" feature-id="true"/>
<param name="a" feature-id="true"/>
</params>
</feature-spec>
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureB">
<refs>
<ref feature="featureP"/>
</refs>
<params>
<param name="parent" feature-id="true"/>
<param name="b" feature-id="true"/>
</params>
</feature-spec>
Now let’s suppose that there is a group which includes features of featureA
and featureB
specs.
<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">
<feature spec="featureA">
<param name="a" value="a1"/>
</feature>
<feature spec="featureB">
<param name="id" value="b1"/>
</feature>
</feature-group-spec>
This group can be nested under any instance of featureP
and parameter parent
of the features in the group will implicitly be initialized to the value of parameter parent
of the outer featureP
instance.
<config name="main">
<feature spec="featureP">
<param name="parent" value="p1"/>
<feature-group name="group1"/>
</feature>
<feature spec="featureP">
<param name="parent" value="p2"/>
<feature-group name="group1"/>
</feature>
</config>
The resulting config will include:
-
featureP:parent=p1
; -
featureP:parent=p2
; -
featureA:parent=p1,a=a1
; -
featureA:parent=p2,a=a1
; -
featureB:parent=p1,b=b1
; -
featureB:parent=p2,b=b1
.
8.2.4. Merging feature groups
There could be a situation when the same feature group is brought into the config as a dependency of a few other feature groups. Which means its basic feature set is included into the final configuration multiple times but, taking into account possible customizations, each time it might be slightly different.
In that case the feature configurations will be merged. The features that are included later in the config will overwrite the common parameters of the corresponding features included earlier. But they will not completely replace the feature configurations that were added earlier. |
For example, suppose we have these feature specs:
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureA">
<params>
<param name="name" feature-id="true"/>
<param name="p1" default="feature-spec"/>
<param name="p2" default="feature-spec"/>
<param name="p3" default="feature-spec"/>
</params>
</feature-spec>
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureB">
<params>
<param name="name" feature-id="true"/>
<param name="p1" default="feature-spec"/>
<param name="p2" default="feature-spec"/>
<param name="p3" default="feature-spec"/>
</params>
</feature-spec>
and these feature groups
<feature-group-spec name="group1" xmlns="urn:jboss:galleon:feature-group:1.0">
<feature spec="featureA">
<param name="name" value="a1"/>
<param name="p1" value="group1"/>
<param name="p2" value="group1"/>
<param name="p3" value="group1"/>
</feature>
<feature spec="featureA">
<param name="name" value="a2"/>
</feature>
<feature spec="featureA">
<param name="name" value="a3"/>
</feature>
<feature spec="featureB">
<param name="name" value="b1"/>
<param name="p1" value="gorup1"/>
<param name="p2" value="group1"/>
<param name="p3" value="group1"/>
</feature>
<feature spec="featureB">
<param name="name" value="b2"/>
</feature>
</feature-group-spec>
<feature-group-spec name="group2" xmlns="urn:jboss:galleon:feature-group:1.0">
<feature-group name="group1">
<include feature-id="featureA:name="a1">
<param name="p1" value="group2"/>
<param name="p2" value="group2"/>
</feature>
<exclude feature-id="featureA:name=a3"/>
<include feature-id="featureB:name="b1">
<param name="p2" value="group2"/>
</feature>
<exclude feature-id="featureB:name=b2"/>
</feature-group>
</feature-group-spec>
<feature-group-spec name="group3" xmlns="urn:jboss:galleon:feature-group:1.0">
<feature-group name="group1">
<include feature-id="featureA:name="a1">
<param name="p1" value="group3"/>
</feature>
<exclude feature-id="featureA:name=a2"/>
<include feature-id="featureB:name="b1">
<param name="p3" value="group3"/>
</feature>
<exclude feature-id="featureB:name=b2"/>
</feature-group>
</feature-group-spec>
Now this configuration
<config name="main">
<feature-group name="group2"/>
<feature-group name="group3"/>
</config>
will contain
Feature spec | name | p1 | p2 | p3 |
---|---|---|---|---|
featureA |
a1 |
group3 |
group2 |
group1 |
featureA |
a2 |
feature-spec |
feature-spec |
feature-spec |
featureA |
a3 |
feature-spec |
feature-spec |
feature-spec |
featureB |
b1 |
group1 |
group2 |
group3 |
8.3. Layers
A layer is meant to represent a certain configuration flavor that can be used on its own or in combination with other layers to produce the final configuration. |
The idea behind layers is to predefine certain technology or some other purpose specific complete configurations (that can be used individually or in combination) and expose them as a multichoice to users composing their desired configuration.
For example, let’s suppose we are provisioning an application server that supports multiple technologies such as EJB, Servlet, Messaging, etc. Those technologies could be viewed as components that make up the complete server but also, possibly, as a user’s choice at installation time, in case the user is actually interested only in a subset of those or perhaps simply one, or something that is not included into the default set.
Layers are defined in feature-pack archive’s layers
directory. A layer is associated with a name but also, as configuration models, can be associated with a model. If a layer is associated with a model, its definition in the feature-pack archive will appear in layers/config_model/layer_name/layer-spec.xml
file, otherwise it will end up in layers/layer_name/layer-spec.xml
.
Layers may depend on other layers. If a configuration includes a layer that depends on another layer, that other layer will be included (unless explicitly excluded by the user) into the configuration as well (prior to the layer declaring the dependency on it).
While layers may be associated with both configuration model and a name, they are always referenced in configuration by simple name. The reason for that is that a layer can be referenced only from a configuration model or another layer and, ultimately, it still goes down to the configuration model that includes the layers. So it is the configuration model that determines which model to use for the layers it includes. |
8.3.1. Layers vs feature groups
Layers and feature groups have the following in common:
-
both are meant to define a certain (specialized) part of the final configuration;
-
both may define package dependencies.
But they also have quite a few significant differences.
Origin
The content of a feature group (including its package dependencies, if any) is fully defined in a single file - the feature group spec XML. And so, a feature group has a specific origin - the feature-pack containing the definition of the feature group.
Layers, on the other hand, are a product of merging layer specs with the same identity (configuration model + layer name combination) from all the feature-packs that make up the installation. From this perspective, layers are closer to configuration models than feature groups. And so, a layer might not have a single origin.
Dependencies
Feature groups don’t really have the notion of dependencies on other feature groups. A feature group may include other feature groups (their content) into its body.
A layer may define dependencies on other layers, which is not the same as including content of those layers into the layer declaring the dependency. The content of layers is merged directly into the configuration model which includes the layers.
Exclusion from configuration
There is no way to exclude feature groups that have been earlier included into the configuration. When a feature group is added to a configuration, its content (features) is merged immediately into the configuration model. In a way, feature groups dissolve in the configuration and there is no way to identify the set of features previously forming the group with the goal to exclude them altogether from the configuration.
Layers, on the other hand, can be excluded from the configuration. When a configuration is resolved, the complete set of layers it includes is determined and then merged into the configuration. A user may provide instructions though to filter certain (or all the) layers out of the configuration.
Nesting
Feature groups can be nested under a feature which would serve as a parent feature for all the features included into the nested group directly and initialize the corresponding ID parameters of all the features contained in the group.
Layers can’t be nested under a feature. They are meant to define a complete configuration or a part of it starting from the very top of it.
8.3.2. Layer spec
A layer spec is defined in layer-spec.xml
file which, for the most part, content-wise is identical to a feature-group spec except it allows to configure dependencies on other layers. Here is an example
<layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="layerA">
<dependencies>
<layer name="layerB"/> (1)
<layer name="layerC" optional="true"/> (2)
</dependencies>
<!-- various features and feature groups -->
<feature spec="specA">
<param name="id" value="1"/>
<param name="p1" value="value"/>
</feature>
<feature-group name="groupA"/>
<packages>
<package name="packageA"/> (3)
<package name="packageB" optional="true"/> (4)
</packages>
</layer-spec>
1 | required dependency on layerB (layerA can’t be installed unless layerB has been installed) |
2 | optional dependency on layerC (layerC will be installed when layerA is installed but if layerC has been excluded by the user, layerA will still be installed) |
3 | required dependency on packageA (layerA can’t be installed unless packageA has been installed) |
4 | optional dependency on packageB (packageB will be installed when layerA is installed but if packageB has been excluded by the user, layerA will still be installed) |
8.3.3. Effective layer spec
In the simplest case, when only one feature-pack among all of the feature-packs that make up the installation defines a layer with a specific identity in the corresponding layer-spec.xml
, whatever is defined in that layer-spec.xml
is the effective layer spec in the installation.
However, in case an installation includes multiple feature-packs that happen to define a layer with the same identity (model and layer name combination) then the effective layer spec with that identity will be the result of merging all the layer specs from all the feature-packs that make up the installation into one. Merging happens in the order the feature-packs are installed and follow the same principle used for merging configuration models.
For example, let’s supposed we have three feature-packs: fpA
, fpB
and fpC
and fpB
depends on fpA
. Every one of those feature-packs defines layer1
.
<layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="layerA">
<feature spec="specA">
<param name="id" value="1"/>
<param name="p1" value="fpA"/>
<param name="p2" value="fpA"/>
<param name="p3" value="fpA"/>
</feature>
<packages>
<package name="package-fpA"/>
</packages>
</layer-spec>
<layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="layerA">
<feature spec="specA">
<param name="id" value="1"/>
<param name="p2" value="fpB"/>
<param name="p3" value="fpB"/>
</feature>
<packages>
<package name="package-fpB"/>
</packages>
</layer-spec>
<layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="layerA">
<feature spec="specA">
<param name="id" value="1"/>
<param name="p3" value="fpC"/>
</feature>
<packages>
<package name="package-fpC"/>
</packages>
</layer-spec>
Now if we provision an installation using the feature-packs above as
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<feature-pack location="fpB@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/> (1)
<feature-pack location="fpC@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
</installation>
1 | fpB installs fpA as its transitive dependency |
The effective layer spec of layerA
will be resolved as
layer1
spec<layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="layerA">
<feature spec="specA">
<param name="id" value="1"/>
<param name="p1" value="fpA"/>
<param name="p2" value="fpB"/>
<param name="p3" value="fpC"/>
</feature>
<packages>
<package name="package-fpA"/>
<package name="package-fpB"/>
<package name="package-fpC"/>
</packages>
</layer-spec>
There won’t actually be an XML file generated for the effective layer spec. The XML above is used only for illustration of the effective layer content and its dependencies. |
As in case of configuration model merging, feature-packs that appear higher in the feature-pack dependency hierarchy are allowed to use include
and/or exclude
elements in their layer specs to include and/or exclude features from the corresponding layers inherited from their feature-pack dependencies. In our example above, include
and/or exclude
elements could be used in layer1
of fpB
to manipulate the content of layer1
inherited from fpA
. E.g.
<layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="layerA">
<exclude spec="specA"/>
<feature spec="specA">
<param name="id" value="1"/>
<param name="p2" value="fpB"/>
<param name="p3" value="fpB"/>
</feature>
<packages>
<package name="package-fpB"/>
</packages>
</layer-spec>
With the rest of the configs unchanged the effective layer1
spec will become
layer1
spec<layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="layerA">
<feature spec="specA">
<param name="id" value="1"/>
<param name="p2" value="fpB"/>
<param name="p3" value="fpC"/>
</feature>
<packages>
<package name="package-fpA"/>
<package name="package-fpB"/>
<package name="package-fpC"/>
</packages>
</layer-spec>
In case of fpC
which doesn’t declare any dependency on neither fpA
nor fpB
, using include
and/or exclude
in its layer1
spec won’t make any sense because other layer1
specs are not 'visible' from fpC
.
8.3.4. Including layers into configuration models
Layers are included into configuration defined using config
element under element layers
, e.g.
<config xmlns="urn:jboss:galleon:config:1.0" model="model1" name="name1">
<layers>
<include name="layer1"/>
<include name="layer2"/>
</layers>
<!-- the rest of the configuration -->
</config>
Let’s suppose the configuration above belongs to a feature-pack prod1
. And prod1
also predefined another layer - layer3
, which is not included into the default configuration model1:name1
. Here is how layer3
can be added to the final configuration by a user:
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<feature-pack location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
<config xmlns="urn:jboss:galleon:config:1.0" model="model1" name="name1">
<layers>
<include name="layer3"/>
</layers>
<!-- the rest of the configuration -->
</config>
</installation>
The resulting model1:name1
configuration now will include layer1
, layer2
and layer3
and they will be included into the configuration in exactly that order.
The statement above is valid only if the mentioned layers don’t depend on each other and/or other layers. |
8.3.5. Excluding layers from configuration models
Layers that have been included into the configuration can later be excluded from it. The example above demonstrated how to include a layer into the configuration, here is an example of how a layer can be excluded:
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<feature-pack location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
<config xmlns="urn:jboss:galleon:config:1.0" model="model1" name="name1">
<layers>
<exclude name="layer2"/>
<include name="layer3"/>
</layers>
<!-- the rest of the configuration -->
</config>
</installation>
Assuming feature-pack prod1
included layer1
and layer2
into its model1:name1
configuration (as in the previous example), the resulting model1:name1
configuration will include only layer1
and layer3
(and their dependencies if any).
An attempt to exclude a layer that would not have otherwise been installed will result in a provisioning error. The error, however, can be suppressed by adding provisioning option ignore-not-excluded-layers .
|
8.3.6. Disabling inheritance of layers
If at some point it is necessary to reset the configuration in terms of layers it consists of and possibly re-define the configuration explicitly, it can be done like this
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<feature-pack location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
<config xmlns="urn:jboss:galleon:config:1.0" model="model1" name="name1">
<layers inherit="false">
<include name="layer3"/>
</layers>
<!-- the rest of the configuration -->
</config>
</installation>
inherit="false"
attribute indicates to the provisioning mechanism to not inherit any layers for the configuration from any of the feature-packs included up to that point. The resulting model1:name1
configuration will include only layer3
(plus its dependencies) even if prod1
included more layers into model1:name1
.
8.3.7. Adjusting layer configuration
Once layers have been included into the configuration, the set of features, as well as packages, they brought in can be manipulated, i.e. configuration of some or all of those features can be modified or completely excluded.
Here is an example. Let’s suppose prod1
feature-pack defines layer1
as
<layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="layer1">
<feature spec="specA">
<param name="id" value="1"/>
</feature>
<feature spec="specA">
<param name="id" value="2"/>
</feature>
<feature spec="specB">
<param name="id" value="1"/>
</feature>
<feature spec="specB">
<param name="id" value="2"/>
</feature>
<packages>
<package name="package1"/>
<package name="package2" optional="true"/>
<package name="package3"/>
</packages>
</layer-spec>
The user wants to include this layer into its installation but also adjust its configuration. It could look like this
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<feature-pack location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<packages>
<exclude name="package2"/> (1)
</packages>
</feature-pack>
<config xmlns="urn:jboss:galleon:config:1.0" model="model1" name="name1">
<layers>
<include name="layer1"/>
</layers>
<exclude feature-id="specA:id=2"/> (2)
<exclude spec="specB"/> (3)
<feature spec="specB">
<param name="id" value="3"/>
</feature>
</config>
</installation>
1 | package2 layer1 depends on is excluded from the installation |
2 | specA:id=2 inherited from layer1 is excluded from the configuration |
3 | All the features of specB inherited from layer1 are excluded from the configuration |
The resulting installation will consist of:
-
model1:name1
configuration including features:-
specA:id=1
-
specB:id=3
-
-
package1
plus its dependencies, if any; -
package3
plus its dependencies, if any.
8.3.8. Merging configurations with layers
Layers are merged into configuration at the point where they are included into it with include
element. It is important to keep that in mind.
Let’s consider the following example. Suppose prod1
feature-pack defines this configuration:
<config xmlns="urn:jboss:galleon:config:1.0" model="model1" name="name1">
<layers>
<include name="layer1"/>
<include name="layer2"/>
</layers>
<!-- the rest of the configuration -->
</config>
prod2
feature-pack depends on prod1
and defines this configuration:
<config xmlns="urn:jboss:galleon:config:1.0" model="model1" name="name1">
<layers>
<include name="layer2"/>
<include name="layer3"/>
</layers>
<!-- the rest of the configuration -->
</config>
When prod2
is installed, layer2
will be included into model1:name1
twice. Which may or may not create a confusion. First of all, in the given example, all the features added to model1:name
in prod1
are inherited by model1:name1
in prod2
, meaning model1:name1
in prod2
does not start empty. layer1
and layer2
have already been added to model1:name1
in prod1
. Including layer2
into model1:name1
in prod2
does not make sense any more unless model1:name1
in prod1
has excluded and/or modified some feature configurations inherited from layer2
and in prod2
we want the original version of layer2
configuration.
Whether including the same layer more than once into the same configuration creates a problem or not depends on the case. It’s important to keep in mind that every include means another merge of the layer.
If the content of the layer has not been adjusted in the configuration, the subsequent merge of the same layer will not result in any visible difference unless the layer includes features that have no identity. If a layer includes features that have no identity, there will be as many copies of those features in the configuration as the number of times the layer has been included into the configuration. |
While the example above can easily be adjusted in case the inclusion of layer2
actually is redundant by simply removing it from the list of layers in prod2
, there could be situations where it’s more difficult to avoid multiple inclusions of the same layer. For example building up the example above, let’s assume that every one of layer1
, layer2
and layer3
depends on layer called base
.
In that case, base
will be included once into model1:name1
in prod1
(despite the fact that both layer1
and layer2
depend on base
, the provisioning mechanism will recognize that base
is a common dependency of those layers and include it only once into model1:name1
in prod1
). But later, processing model1:name
in prod2
, it will include base
again as a dependency of layer3
.
THIS CAN CHANGE. The mechanism can recognize that base has already been included and avoid including it again. The only possible issue is that if layer3 really expects the original base configuration and the already included base has been somehow modified in between.
|
9. Provisioned installation configuration
9.1. Configuration model attributes
Every configuration must be associated with at least one of the following attributes:
-
name
- name of the configuration; -
model
- name of the configuration model.
name
and model
attributes serve as the identity of the configuration. They are essential when customizing and merging configurations.
If a configuration is associated only with a name (and no model) then only the name will be used as the identity of the configuration.
If a configuration is associated with a name and a model then the combination of the name and the model will be used as the identity of the configuration.
Feature-pack may include predefined configurations in its configs
directory whose structure can be described as
configs/ |- model1/ | |- name1/ | | `- config.xml | | ... | |- nameN/ | | `- config.xml | `- model.xml | ... |- modelM/ | |- name1/ | | `- config.xml | | ... | |- nameN/ | | `- config.xml | `- model.xml |- name1/ | `-config.xml | ... `- nameN/ `-config.xml
If a configuration is associated with a name but not a model then its definition will be located in configs/config_name/config.xml
and start with the following root element:
<config xmlns="urn:jboss:galleon:config:1.0" name="config_name">
<!-- skipped content -->
</config>
If a configuration is associated only with a model then its definition will located in configs/config_model/model.xml
and start with the following root element:
<config xmlns="urn:jboss:galleon:config:1.0" model="config_model">
<!-- skipped content -->
</config>
If a configuration is associated with both model and a name its definition will be located in configs/model_name/config_name/config.xml
and start with the following root element:
<config xmlns="urn:jboss:galleon:config:1.0" model="model_name" name="config_name">
<!-- skipped content -->
</config>
Predefined configuration models can be referenced from feature-pack.xml
file and customized (manipulated) in the provisioning configuration of the installation (which is also an XML file) using config
elements. Every config
element will include the corresponding name
and possibly model
attributes to specify the identity of the configuration it is targeting.
Every config element in feature-pack.xml or installation provisioning configuration triggers installation of the configuration it is targeting.
|
That means, when a feature-pack is installed, by default all the configurations referenced from its feature-pack.xml
are installed. Users may explicitly specify though which configurations should the final distribution include and customize those and/or provide their own custom configurations in the provisioning configuration of the installation.
Here is an example of feature-pack.xml
with config
elements:
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0">
<config name="config1">
<!-- named configuration -->
</config>
<config model="model1" name="config1">
<!-- named configuration of model1 -->
</config>
</feature-pack>
9.2. Excluding default configs from the installation
The simplest way to exclude configs from the installation is
<installation xmlns="urn:jboss:galleon:provisioning:1.0">
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<default-configs inherit="false"/>
</feature-pack>
</installation>
inherit="false"
attribute indicates that none of the configs should be included into the distribution by default. If the attribute is not present, its value is assumed to be true
.
feature-pack element in the example above could as well appear under dependecies element of feature-pack.xml . Meaning the XML type of these elements are equivalent - they both describe a customized feature-pack. The examples below will be showing only feature-pack element.
|
The example above excludes all the configs, if the goal however is to exclude onyl a specific one, it can be done by providing the identity of the config using exclude
element. For example, if a configuration was associated with a name but not any model then it would look like this:
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<default-configs>
<exclude name="config1"/>
</default-configs>
</feature-pack>
And if the configuration was associated with a name and a model, both of them will have to be specified, e.g.
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<default-configs>
<exclude name="config1" model="model1"/>
</default-configs>
</feature-pack>
In case there are multiple named configs that are associated with the same model, e.g.
<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<config model="model1" name="config1">
<!-- config body -->
</config>
<config model="model1" name="config2">
<!-- config body -->
</config>
<config model="model2" name="config1">
<!-- config body -->
</config>
<config model="model2" name="config2">
<!-- config body -->
</config>
</feature-pack>
<installation xmlns="urn:jboss:galleon:provisioning:1.0">
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<default-configs>
<exclude model="model1"/>
</default-configs>
</feature-pack>
</installation>
This installation will include configs model2:config1
and model2:config2
.
9.3. Picking default configs into the installation
There are two scenarios when including a configuration could be necessary:
-
when the configuration was excluded with
<exclude model="model_name"/>
; -
when inhertance of the default configurations was disabled with
<default-configs inherit="false">
.
The first one of course assumes that the configuration is associated with both name and model. It could look like this:
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<default-configs>
<exclude model="model1"/>
<include name="config1" model="model1"/>
</default-configs>
</feature-pack>
The example above excludes all the model1
configurations except config1
.
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<default-configs inherit="false">
<include name="config1"/>
<include name="config1" model="model1"/>
</default-configs>
</feature-pack>
The example above picks only config1
and model1:config1
from all the default configurations to be included into the distribution.
It is also possible to include configurations of a specific model, e.g.
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<default-configs inherit="false">
<include model="model1"/>
</default-configs>
</feature-pack>
In this case, all the default configurations of model1
will be included into the distribution.
9.4. Configuration model merges
Configuration model merging is a way to integrate various products in the same installation. Lets suppose we want to add new product to an existing installation. Besides adding its filesystem content to the installation, normally, the configuration files of the existing installation will have to be adjusted to include the configuration of the product to be added.
In the provisioning terms, this scenarios can be described as:
-
there is a feature-pack (or a few) of the main installation (defining its FS content as well as the configurations);
-
there is the other product’s feature-pack defining its filesystem content and its default configuration that should be added to the main installation as part of its integration.
How exactly the configuration of the new product is integrated into the existing installation will depend on every specific case but there are a few basic ways it can happen:
-
the product comes with its own standalone configuration which will not affect the existing installation configuration in any way;
-
the product configuration will have to be added to the existing configuration of the installation;
-
a combination of the two above: the standalone configuration and a piece of the configuration that needs to be added to the existing configuration of the installation.
The first one is simple: we just need to create two separate configurations: one for the main installation and one for the product we integrate.
In the second case, we need to actually merge the configurations from the existing installation and the feature-pack which represents the new product into a single confguration.
The third one effectively means that we’ve got multiple configuration models some of which should be merged and some should remain standalone. The tricky part is to identify which one is which. This is where the configuration name
and model
attributes are useful.
The provisioned installation may contain only one configuration model of a specific identity (which is the product of config
name
and model
attribute values).
When the provisioning mechanism analysing the installation being provisioned discovers multiple configuration models with the same identity, it does not throw an error but merges the configuration models into a single one (which may still result in an error, of course, if the resulting model contains unsatisfied requirements). |
9.4.1. Named (name-only) configurations
The simplest way to provide an identity for a configuration is to give it a name. E.g.
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<config name="config1"/>
</feature-pack>
<config xmlns="urn:jboss:galleon:config:1.0" name="config1">
<feature spec="feature1">
<param name="id" value="1"/>
<param name="a" value="fp1"/>
<param name="b" value="fp1"/>
</feature>
<feature spec="feature2">
<param name="id" value="1"/>
</feature>
</config>
Now if another feature-pack provides a configuration with the same name, e.g.
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<config name="config1"/>
</feature-pack>
<config xmlns="urn:jboss:galleon:config:1.0" name="config1">
<feature spec="feature1">
<param name="id" value="1"/>
<param name="b" value="fp2"/>
</feature>
<feature spec="feature3">
<param name="id" value="1"/>
</feature>
</config>
And we include both of these feature-packs into the same installation
<installation xmlns="urn:jboss:galleon:provisioning:1.0">
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
<feature-pack location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
</installation>
The provisioned config1
will be the result of merging config1
from fp2
into config1
from fp1
.
Which config overwrites which (assuming they contain common parts) depends on the order in which the feature-packs are listed under installation element.
|
Here is the content of the provisioned config1
:
Feature spec origin | Feature spec | id | a | b |
---|---|---|---|---|
fp1@maven(org.jboss.universe:community-universe)1#1.0.0.Final |
feature1 |
1 |
fp1 |
fp1 |
Feature spec origin | Feature spec | id |
---|---|---|
fp1@maven(org.jboss.universe:community-universe)1#1.0.0.Final |
feature2 |
1 |
Feature spec origin | Feature spec | id | b |
---|---|---|---|
fp2@maven(org.jboss.universe:community-universe)1#1.0.0.Final |
feature1 |
1 |
fp2 |
Feature spec origin | Feature spec | id |
---|---|---|
fp2@maven(org.jboss.universe:community-universe)1#1.0.0.Final |
feature3 |
1 |
The features of feature1 spec are not merged although they appear to have the same ID. The reason is that fp2 does not declare the dependency on fp1 and its feature specs are not available in fp2 configurations. So this example assumes that both fp1 and fp2 include feature spec feature1 .
|
Here is how feature-pack.xml
of fp2
had to be written so that feature1
spec could be re-used in fp2
configuration:
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp2@maven(org.jboss.universe:community-universe)1#1.0.0.Final">
<dependencies>
<dependency location="fp1@maven(org.jboss.universe:community-universe)1#1.0.0.Final"/>
</dependencies>
<config name="config1"/>
</feature-pack>
With this feature-pack configuration the resulting config1
will include the following features:
Feature spec origin | Feature spec | id | a | b |
---|---|---|---|---|
fp1@maven(org.jboss.universe:community-universe)1#1.0.0.Final |
feature1 |
1 |
fp1 |
fp2 |
Feature spec origin | Feature spec | id |
---|---|---|
fp1@maven(org.jboss.universe:community-universe)1#1.0.0.Final |
feature2 |
1 |
Feature spec origin | Feature spec | id |
---|---|---|
fp2@maven(org.jboss.universe:community-universe)1#1.0.0.Final |
feature3 |
1 |
9.4.2. Named model configurations
There are a couple of reasons for adding model
attribute to the configuration identity. One of them is to define the scope for values of attribute name
. In this sense, a model
could be thought of as a namespace. E.g.
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<config name="main" model="modelA"/>
<config name="main" model="modelB"/>
</feature-pack>
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelA">
<feature spec="feature1">
<param name="id" value="1"/>
<param name="a" value="fp1-modelA"/>
<param name="b" value="fp1-modelA"/>
</feature>
</config>
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelB">
<feature spec="feature1">
<param name="id" value="1"/>
<param name="a" value="fp1-modelB"/>
<param name="b" value="fp1-modelB"/>
</feature>
</config>
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<dependencies>
<dependency location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
</dependencies>
<config name="main" model="modelA"/>
<config name="main" model="modelB"/>
</feature-pack>
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelA">
<feature spec="feature1">
<param name="id" value="1"/>
<param name="b" value="fp2-modelA"/>
</feature>
</config>
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelB">
<feature spec="feature1">
<param name="id" value="1"/>
<param name="b" value="fp2-modelB"/>
</feature>
</config>
Installing these two feature-packs (fp2
following fp1
) will result in the following two configurations:
Feature spec origin | Feature spec | id | a | b |
---|---|---|---|---|
fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final |
feature1 |
1 |
fp1-modelA |
fp2-modelA |
Feature spec origin | Feature spec | id | a | b |
---|---|---|---|---|
fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final |
feature1 |
1 |
fp1-modelB |
fp2-modelB |
9.4.3. Model-only configurations
Model-only configurations are associated only with a model by means of model
attribute of config
element but are not associated with any name specific name.
The idea behind the model-only configurations is to be able to define the base for a configuration of a specific model that every final configuration of that model should include. Model-only configurations are always added into the configuration before the named configurations, i.e. named configurations will be added on top of the model-only ones and will overwrite them.
At the end, a provisioned installation will only contain the named configurations but not the model-only ones. Model-only configurations are always merged into the named configurations. |
A model-only configuration is merged into all the named configurations of the installation associated with the same model as the model-only configuration. |
Let’s look at an example. Suppose we have two feature-packs: fp1
and fp2
.
fp1
is defined as
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<config name="main" model="modelB"/>
</feature-pack>
And includes the following configurations
<config xmlns="urn:jboss:galleon:config:1.0" model="modelA">
<feature spec="feature1">
<param name="id" value="1"/>
<param name="a" value="fp1-modelA"/>
<param name="b" value="fp1-modelA"/>
</feature>
</config>
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelB">
<feature spec="feature1">
<param name="id" value="1"/>
<param name="b" value="fp1-modelB"/>
</feature>
</config>
fp2
is defined as
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<dependencies>
<dependency location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
</dependencies>
<config name="main" model="modelA"/>
<config name="test" model="modelA"/>
<config name="test" model="modelB"/>
</feature-pack>
And includes the following configurations
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelA">
<feature spec="feature1">
<param name="id" value="1"/>
<param name="b" value="fp2-modelA"/>
</feature>
</config>
<config xmlns="urn:jboss:galleon:config:1.0" name="test" model="modelA">
<feature spec="feature2">
<param name="id" value="1"/>
<param name="a" value="fp2-modelA"/>
<param name="b" value="fp2-modelA"/>
</feature>
</config>
<config xmlns="urn:jboss:galleon:config:1.0" model="modelB">
<feature spec="feature1">
<param name="id" value="1"/>
<param name="a" value="fp2-modelB"/>
<param name="b" value="fp2-modelB"/>
</feature>
</config>
<config xmlns="urn:jboss:galleon:config:1.0" name="test" model="modelB">
<feature spec="feature2">
<param name="id" value="1"/>
<param name="a" value="fp2-modelB"/>
<param name="b" value="fp2-modelB"/>
</feature>
</config>
Installing these two feature-packs will result in the following configurations:
Feature spec origin | Feature spec | id | a | b |
---|---|---|---|---|
fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final |
feature1 |
1 |
fp1-modelA |
fp2-modelA |
Feature spec origin | Feature spec | id | a | b |
---|---|---|---|---|
fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final |
feature1 |
1 |
fp1-modelA |
fp1-modelA |
fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final |
feature2 |
1 |
fp2-modelA |
fp2-modelA |
Feature spec origin | Feature spec | id | a | b |
---|---|---|---|---|
fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final |
feature1 |
1 |
fp2-modelB |
fp1-modelB |
Feature spec origin | Feature spec | id | a | b |
---|---|---|---|---|
fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final |
feature1 |
1 |
fp2-modelB |
fp2-modelB |
fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final |
feature2 |
1 |
fp2-modelB |
fp2-modelB |
Excluding model-only configurations with exclude element
Normally, model-only configurations are not supposed to be explicitly excluded. If a user excludes all the named configs of a specific model, the model-only configs of that model will simply be ignored by the provisioning mechanism.
Configuration model designers are encouraged to model configurations in a way that model-only configurations represent an essential part of any configuration of that model and its runtime dependencies and don’t need to be excluded explicitly by users or should be excluded in exceptional cases. |
In a previous chapter it was described how the default configurations could be excluded from the provisioned installation by specifying their model name. Here is the relevant part of the configuration:
<installation xmlns="urn:jboss:galleon:provisioning:1.0">
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<default-configs>
<exclude model="model1"/>
</default-configs>
</feature-pack>
</installation>
exclude
element above does not affect the model-only configurations. It affects only the named configurations associated with the specified model.
Let’s imagine we have the following feature-pack fp1
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<config name="main" model="modelA"/>
</feature-pack>
with the following configurations
<config xmlns="urn:jboss:galleon:config:1.0" model="modelA">
<feature spec="feature1">
<param name="id" value="1"/>
<param name="a" value="fp1-modelA"/>
<param name="b" value="fp1-modelA"/>
<param name="c" value="fp1-modelA"/>
</feature>
</config>
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelA">
<feature spec="feature1">
<param name="id" value="1"/>
<param name="b" value="fp1-modelA-main"/>
</feature>
</config>
And feature-pack fp2
<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<dependencies>
<dependency location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
</dependencies>
<config name="main" model="modelA"/>
</feature-pack>
With the following configuration
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelA">
<feature spec="feature1">
<param name="id" value="1"/>
<param name="c" value="fp2-modelA-main"/>
</feature>
</config>
If we install these feature-packs the resulting configuration will contain
Feature spec origin | Feature spec | id | a | b | c |
---|---|---|---|---|---|
fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final |
feature1 |
1 |
fp1-modelA |
fp1-modelA-main |
fp2-modelA-main |
If we exclude modelA
like it was shown in the previous example in the declaration of the dependency on fp1
, i.e.
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<dependencies>
<dependency location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<default-configs>
<exclude model="modelA"/>
</default-configs>
</dependency>
</dependencies>
<config name="main" model="modelA"/>
</feature-pack>
If we install fp2
now, the provisioned configuration will contain
Feature spec origin | Feature spec | id | a | b | c |
---|---|---|---|---|---|
fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final |
feature1 |
1 |
fp1-modelA |
fp1-modelA |
fp2-modelA-main |
The model-only configuration from fp1
is still effective because fp1
is installed as a dependency of fp2
and its modelA
configuration is considered being essential for any named configuration of the model. In case it still has to be excluded from the provisioned configuration it can be done by adding named-only-models="false"
attribute to exclude
element, e.g.
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<dependencies>
<dependency location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<default-configs>
<exclude model="modelA" named-only-models="false"/>
</default-configs>
</dependency>
</dependencies>
<config name="main" model="modelA"/>
</feature-pack>
exclude
element above affects both named and model-only configurations of modelA
from feature-pack fp1
.
named-only-models attribute is optional and if abscent its value is assumed to be true .
|
The provisioned configuration of fp2
will now contain
Feature spec origin | Feature spec | id | c |
---|---|---|---|
org.jboss.pm.test:fp1:1.0.0.Final |
feature1 |
1 |
fp2-modelA-main |
Disabling inheritance of model-only configurations
In an earlier chapter it was shown how the default configurations of a feature-pack could be suppressed. Let’s now include a model-only configuration in the example.
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<config name="main" model="modelA"/>
</feature-pack>
<config xmlns="urn:jboss:galleon:config:1.0" model="modelA">
<feature spec="feature1">
<param name="id" value="1"/>
<param name="a" value="fp1-modelA"/>
<param name="b" value="fp1-modelA"/>
<param name="c" value="fp1-modelA"/>
</feature>
</config>
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelA">
<feature spec="feature1">
<param name="id" value="1"/>
<param name="b" value="fp1-modelA-main"/>
</feature>
</config>
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<dependencies>
<dependency location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<default-configs inherit="false"/> (1)
</dependency>
</dependencies>
<config name="main" model="modelA"/>
</feature-pack>
1 | the default configurations from fp1 are going to be ignored |
<config xmlns="urn:jboss:galleon:config:1.0" name="main" model="modelA">
<feature spec="feature1">
<param name="id" value="1"/>
<param name="c" value="fp2-modelA-main"/>
</feature>
</config>
With inherit="false"
attribute of default-configs
element we indicated that the default configurations of fp1
should not be included into the distribution provisioned from fp2
. But it does not affect the model-only configs. So the model-only modelA
configuration will still be effective in fp2
.
inherit-unnamed-models attributes of default-configs element controls whether the model-only configs are inherited or not. The attribute is optional and if not present, its value is assumed to be true .
|
Here is an example that disables the inheritance of all the named and model-only configurations:
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<dependencies>
<dependency location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<default-configs inherit="false" inherit-unnamed-models="false"/>
</dependency>
</dependencies>
<config name="main" model="modelA"/>
</feature-pack>
The installation provisioned from fp2
will include the following configuration
Feature spec origin | Feature spec | id | c |
---|---|---|---|
fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final |
feature1 |
1 |
fp2-modelA-main |
9.5. Content of config
element
Although this chapter is describing config element as a child of feature-pack element, the same applies to the root config element from config.xml and model.xml files.
|
config
element is basically an extended version of feature-group
element. Meaning that everything that is allowed in the body of feature-group
(which is feature
, feature-group
and origin
elements for explicit dependency origins) is allowed in config
element.
Besides that config
element supports already mentioned in an earlier chapter the config attributes and props
element.
When a config element appears in a feature-pack.xml file or as a child of installation element in the provisioning configuration of the installation, it represents all the configurations with the matching identity from all the feature-packs dependency hierarchy up to the current point merged into one configuration model.
|
E.g. if feature-pack fp1
depends on feature-pack fp2
which includes configuration model m1
named n1
. Element config
with attributes model="m1" name="n1"
added to fp1
will represent the corresponding configuration from fp2
(unless the configuration inheritance was explicitly disabled in fp1
), i.e. the content of configuration m1:n1 from fp2
may be manipulated in config
element in fp1
by excluding certain features or overwriting their parameters.
The same applies to config
elements under installation
element. If installation
includes feature-packs fp3
and fp4
, both of which include configs m1:n1
, config
element with attributes model="m1" name="n1"
added under the installation
element will represent the result of merging configs m1:n1
from feature-packs fp3
and fp4
.
9.5.1. Configuration properties
props
element allows to attach various properties to the configuration that can be meaningful to the provisioning plugins processing the configuration. E.g.
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<config name="main" model="modelA">
<props>
<prop name="save-to-file" value="model-a.xml"/>
<prop name="other" value="thing"/>
</props>
<feature spec="feature1">
<param name="id" value="1"/>
<param name="a" value="fp1-modelA"/>
</feature>
</config>
</feature-pack>
9.5.2. Overwriting configuration properties during inclusion
When a default configuration is included, its properties can be overwritten, e.g.
<installation xmlns="urn:jboss:galleon:provisioning:1.0">
<feature-pack location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<default-configs>
<include name="main" model="modelA">
<props>
<prop name="save-to-file" value="main-model-a.xml"/>
</props>
</include>
</default-configs>
</feature-pack>
</installation>
The resolved configuration will include the following properties:
-
save-to-file=main-model-a.xml;
-
other=thing.
9.5.3. Overwriting configuration properties during merging
When the configurations are merged, their properties are also merged. The configuration that is included later into the installation overwrites the properties of the configuration which was added earlier. E.g.
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<config model="modelA">
<props>
<prop name="save-to-file" value="model-a.xml"/>
<prop name="other" value="thing"/>
</props>
<feature spec="feature1">
<param name="id" value="1"/>
<param name="a" value="fp1-modelA"/>
</feature>
</config>
</feature-pack>
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<dependencies>
<dependency location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
</dependencies>
<config name="main" model="modelA">
<props>
<prop name="save-to-file" value="main-model-a.xml"/>
</props>
<feature spec="feature1">
<param name="id" value="1"/>
<param name="a" value="fp2-modelA"/>
</feature>
</config>
</feature-pack>
The resolved configuration modelA:main
will contain the following properties:
-
save-to-file=main-model-a.xml;
-
other=thing.
9.6. Configuration package dependencies
config
elements may include feature-pack package dependencies. So that when a configuration is included into the installation, the relevant packages required by the configuration are automatically included as well. Package dependencies are configured using the same elements described in the feature-package dependencies. E.g.
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<config model="modelA">
<packages>
<package name="p1"/>
<package name="p2" optional="true"/>
</packages>
</config>
</feature-pack>
Now every configuration of modelA
will depend on and bring into the installation the specified packages.
9.7. Configuration dependencies
When all the configuration models have been resolved by the provisioning mechanism, the plugins attached to the installed feature-packs are invoked to generate the final configuration files. The plugins will see the resolved configurations as a list. Certain configuration models though may depend on other configuration models being generated first. To eliminate the trouble of ordering the configurations according to their dependencies in the plugins, configuration dependencies can be expressed in config
elements. E.g.
<config model="host">
<config-deps>
<config-dep id="domain-dep" model="domain"/>
</config-deps>
</config>
In the example above all the configurations of model host
will appear in the resolved config list after all the configurations of model domain
. config-dep
id
is used to identify the configuration dependencies when the configuration models are merged.
The example above illustrates a dependency on a configuration model. But config-dep
may also include name
attribute.
9.8. Arranging features in configurations
Resolved configuration models are meant to be further processed by the provisioning plugins that actually generate the final configuration files. A resolved configuration is basically a set of features and properties. Plugins simply iterate through the features in the resolved configuration and generate the corresponding configuration fragments for the installation.
The order in which features appear in the resolved configuration may be significant. By default the order of the features in the resolved configuration reflects the order in which the features were added to the configuration, i.e. the order in which the features appeared in the config
element. Although, in case there are dependencies between features, the mechanism will re-order the features according to their dependencies, i.e. if feature F1
depends on feature F2
, even if F1
was added to the configuration before F2
, in the resolved configuration F2
will appear before F1
.
9.8.1. Feature branches
Features in the resolved configuration are actually organized into branches. In the simplest case, there is only one branch for all the features of the configuration.
There are cases though, when a certain set of features has to be handled in a different way than the rest of the features in the same configuration. E.g. there could be a few features that form a circular dependency. The mechanism automatically detects those and notifies the plugins in case they need to handle them in a special way. Other examples of branches will be described below.
9.8.2. Batches
Batch is a branch features of which have to be handled atomically. E.g. if processing a feature by a plugin changes a certain state of the model during generation of the final configuration then to avoid a potentionally temporary inconsistent state, batches indicate to the plugins that a specific set of features has to be processed together as a unit and as a single configuration change.
One example could be features that form circular dependencies. Handling them one by one may result in referential integrity (or some other kind of) constraint violation during the final configuration generation.
By default, branches are not flagged as batches. This can be configured though with property config.branch-is-batch
. E.g.
<config model="standalone"> <props> <prop name="config.branch-is-batch" value="true"/> </props> <!-- the rest is skipped -->
The fragment above makes all the branches of all the standalone
configuration models in the installation batches by default.
Batch flag can further be enabled or disabled for a specific branch with feature spec annotations.
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="core-service.management"> <annotation name="feature-branch"> <elem name="id" value="core-service.management"/> <elem name="batch" value="true"/> </annotation> <!-- the rest is skipped -->
This marks branch core-service.management
as batch.
9.8.3. Branch per feature spec
In some cases it might be useful to arrange features in the resolved configuration by their specs. Some plugins may find it more optimal to process, e.g., all the features of Spec1
first then all the features of Spec2
, etc. The mechanism can be instructed to do that by including property config.branch-per-spec
in config
element, e.g.
<config model="standalone"> <props> <prop name="config.branch-per-spec" value="true"/> </props> <!-- the rest is skipped -->
the resulting branches of the configuration will be ordered according to the feature dependencies. E.g. if features of Spec1 reference features of Spec2 , the branch of features Spec2 will appear in the configuration before the branch of features Spec1 .
|
The example above is arranging all the features in the configuration by specs. In some cases though it would be useful to group only features of specific specs together and leave the rest of the features as they are. This can be configured by adding the following feature spec annotation
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="core-service.management"> <annotation name="feature-branch"> <elem name="spec" value="true"/> </annotation> <!-- the rest is skipped -->
9.8.4. Isolating circular dependencies
The mechanism may identify circular dependencies between features in a configuration and create a separate branch for them. Here is how to enable this
<config model="standalone"> <props> <prop name="config.isolate-circular-deps" value="true"/> </props> <!-- the rest is skipped -->
9.8.5. Parent-children branch
Often features in configurations form parent-children relationships. Some plugins may find it useful to receive features arranged as parent-children branches. This can be configured per feature spec. E.g.
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="SpecP"> <annotation name="feature-branch"> <elem name="parent-children"/> </annotation> <!-- the rest is skipped -->
Which means every feature of spec SpecP
will start a branch containing all the features that are children (direct or transitive) of the SpecP
feature.
9.8.6. Branches with explicit IDs
When a branch is created, the mechanism assigns an ID to the branch. A user may instruct the mechanism to group features of certain specs on a branch with a given ID. E.g.
<feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="Spec1"> <annotation name="feature-branch"> <elem name="id" value="Branch1"/> </annotation> <!-- the rest is skipped --> </feature-spec> <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="Spec2"> <annotation name="feature-branch"> <elem name="id" value="Branch1"/> </annotation> <!-- the rest is skipped --> </feature-spec>
In the example above features of Spec1
and Spec2
will be collected on the same branch Branch1
.
9.8.7. Merging independent branches
After a configuration has been resolved, it may appear that some branches share certain common characteristics. E.g. most probably some features in the configuration will depend other features. Which makes the corresponding feature branches depend on other feature branches. There could be a few branches though that don’t depend on other branches (although there could be branches that depend on them). To reduce the total number of branches per configuration, independent branches could be merged into a single independent branch. This can be configured by adding the following property to the config
element
<config model="standalone"> <props> <prop name="config.merge-independent-branches" value="true"/> </props> <!-- the rest is skipped -->
9.8.8. Merging branches with the same dependencies
While the previous option merges only the independent branches, this one identifies branches with the same dependencies on other branches and merges them into a single branch. It can be enabled by adding the following property
<config model="standalone"> <props> <prop name="config.config.merge-same-deps-branches" value="true"/> </props> <!-- the rest is skipped -->
10. Patches
The provisioning mechanism also supports feature-pack patching. Once a feature-pack has been released, the producer of the feature-pack may release patches for it. A patch could overwrite certain content of the feature-pack it applies to (i.e. certain packages or resources) and/or overwrite or re-define a part of the configuration.
A patch itself is also a feature-pack. The only thing that differentiates it from a usual feature-pack is element patch
in its feature-pack.xml
. Here is an example:
<feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
location="producer1@maven(org.jboss.universe:community-universe):1#1.0.0.Patch1.Final">
<patch for="prod1@maven(org.jboss.galleon.universe.test:test-universe):1#1.0.0.Final"/> (1)
<default-packages>
<package name="p1"/>
</default-packages>
</feature-pack>
1 | indicates that the feature-pack is a patch which applies to the feature-pack specified as the value of for attribute |
There is not currently any restriction on the patch feature-pack versioning. 1.0.0.Patch1.Final above is just a random example.
|
Patches can only be applied to a specific version of the feature-pack. An attempt to apply a patch to an installation that does not include the feature-pack version the patch was built for will result in a failure. |
As any other feature-pack, a patch can be installed and uninstalled.
It is possible to apply multiple patches to the same feature-pack in the installation. |
10.1. What can be patched
Patch basically provides a new version of certain content and/or redefines some configuration from the feature-pack it targets. Here is what can be patched:
-
packages (including their content and definitions);
-
feature specs (by providing updated feature specs);
-
feature groups (by providing updated feature groups);
-
layers;
-
configs;
-
various feature-pack resources;
-
provisioning plugins (by including new versions of the plugins).
Patches may also include content that is not present in the feature-pack that apply to (i.e. new packages, feature specs, groups, resources, plugins). |
10.2. Multiple patches for the same feature-pack
As it was mentioned earlier, it is possible to apply multiple patches for the same feature-pack. In case patches don’t overlap in terms of what they patch, the order in which they are applied is not significant. If patches do overlap, the order in which they are applied most probably becomes significant. Because the patch that is applied last will overwrite patches that were applied before it.
Like any other feature-pack, patches may declare dependencies on other patches. That could be one of the ways to control the order in which the patches will be applied. |
10.3. Applying patches
feature-pack
element may include element patches
which lists patches that should be installed for the feature-pack. E.g.
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<feature-pack location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<patches>
<patch id="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Patch1.Final"/>
<patch id="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Patch2.Final"/>
</patches>
</feature-pack>
</installation>
10.3.1. Patching transitive dependencies
It is also possible to apply patches to transitive dependencies. E.g.
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<transitive>
<feature-pack location="prod2@maven(org.jboss.universe:community-universe):1#1.0.0.Final">
<patches>
<patch id="prod2@maven(org.jboss.universe:community-universe):1#1.0.0.Patch1.Final"/>
<patch id="prod2@maven(org.jboss.universe:community-universe):1#1.0.0.Patch2.Final"/>
</patches>
</feature-pack>
</transitive>
<feature-pack location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
</installation>
11. Handling user-managed content
Once an installation has been built, a user or a process (on behalf of the user) may apply certain changes to the content of the installation such as add, edit or remove files and/or directories.
Since these kind of changes are not performed by the provisioning mechanism, it is the responsibility of the user to apply them in a safe manner and not break the installation by introducing some sort of unsatisfied dependencies or violating integrity constraints. |
Since these kind of changes are usually going to be applied after the installation has been built they don’t interfere with the provisioning process. That is until the next (provisioning state) update.
When a user requests a version update or install/uninstall a patch or a feature-pack, or an undo for the installation that contains user-managed content or changes, the provisioning mechanism detects what exactly has changed since the last provisioned state.
If no user changes have been detected, the updated version of the installation will replace the current one. However, if the provisioning mechanism did detect certain changes to the last provisioned state (in the form of added/remove files and/or directories or editted files), those changes will be respected and re-applied to the updated installation state, i.e.
-
files and/or directories added to the previous installation state will be added to the updated installation state;
-
files and/or directories removed from the previous installation state will be removed from the updated installation state;
-
files editted in the previous installation state will be copied over to the updated installation state.
The provisioning mechanism DOES NOT perform 3-way merges on files that have changed in the updated installation state since the last provisioned state and that have also been modified by the user. |
11.1. Application of user changes to the updated installation state
Target in the updated state | Change applied to the updated state |
---|---|
Not found |
The user-added file is copied to the updated state |
Found and matches the file added by the user |
None |
Found and is different from the file added by the user |
|
Target in the updated state | Change applied to the updated state |
---|---|
Not found |
The user-modified file is copied to the updated state and a warning is logged saying that the (equivalent of the) file modified in the previous state is not found in the updated state |
Found and matches the resulting file modified by the user |
None |
Found and is different from the resulting file modified by the user |
|
Target in the updated state | Change applied to the updated state |
---|---|
Not found |
None |
Found |
The target is removed from the updated installation |
Target in the updated state | Change applied to the updated state |
---|---|
Not found |
The corresponding directory is created in the updated state |
Found |
None |
11.2. Protected system files
An installation may contain files and directories that are meant to be managed exclusively by feature-packs and the provisioning tools and not by users. For example, core system libraries of the installation.
Such paths can be marked as system-paths in the feature-pack.xml
.
If during an update a file matching a feature-pack’s system-path was found to be modified by a user, the provisioning mechanism will create a copy of the user-modified file adding the .glold suffix to it and replace the original one with the file provided by the feature-pack.
Target path in the updated state | Change applied to the target path |
---|---|
Not found |
The user-added file is copied to the updated state |
Found and matches the file added by the user |
None |
Found and is different from the file added by the user |
|
Target path in the updated state | Change applied to the target path |
---|---|
Not found |
The user-modified file is copied to the updated state and a warning is logged indicating that the (equivalent of the) file modified in the previous state is not found in the updated state |
Found and matches the resulting file modified by the user |
None |
Found and is different from the resulting file modified by the user |
|
Target path in the updated state | Change applied to the target path |
---|---|
Not found |
None |
Found |
The target is restored to the updated state. |
Target path in the updated state | Change applied to the target path |
---|---|
Not found |
The corresponding directory is created in the updated state |
Found |
None |
12. Provisioning options
Every provisioning action (such as provision
, install
, uninstall
, etc) may accept provisioning options. Provisioning options may control various things, e.g. enable debug mode in one of the product-specific provisioning plugins, activate a certain provisioning mode, etc.
12.1. Persistent and non-persistent options
Provisioning options can be persistent and non-persistent.
Persistent options are persisted in the provisioning configuration file when the provisioning process has succesfully finished. E.g. if prod1
is installed with option1
, the provisioned configuration will look like this
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<feature-pack location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
<options>
<option name="option1" value="true"/>
</options>
</installation>
Now if the user installs prod2
, option1
will still be effective during re-provisioning and the config will change to
<installation xmlns="urn:jboss:galleon:provisioning:2.0">
<feature-pack location="prod1@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
<feature-pack location="prod2@maven(org.jboss.universe:community-universe):1#1.0.0.Final"/>
<options>
<option name="option1" value="true"/>
</options>
</installation>
Option values are not necessarily true or false , they may have various values. The only restriction is they must have some value.
|
Non-persistent options, on the other hand, are not automatically stored in the provisioning configuration. They are used only for the provisioning action they were specified for.
12.2. Built-in and product-specific options
Provisioning options can be provided by the core provisioning mechanism itself and the product-specific provisioning plugins.
12.2.1. Built-in provisioning options
Name |
Purpose |
Value set |
config-stability-level |
Stability level for configs. This stability level is used to enable the stability level of all features present in the generated configurations. By default the configs stability level set in the feature-pack is used. |
|
export-system-paths |
Store the system paths declared by Feature Packs in .galleon/systempaths.txt |
|
ignore-not-excluded-layers |
Suppresses the error when layers configured to be excluded would not have otherwise been installed |
|
optional-packages |
|
|
package-stability-level |
Stability level for packages. This stability level is used to set the stability level of all provisioned packages. By default the packages stability level set in the feature-pack is used. |
|
stability-level |
Stability level for both configs and packages. This option is a convenience
allowing to set both the config and package stability level using a single option. It can’t be set when |
|
store-input-provisioning-config |
Store the provisioning config received as input in the generated .galleon/provisioning.xml file |
|
version-convergence |
|
12.2.2. Product provisioning options
Product-specific provisioning options are exposed by the product-specific provisioning plugins attached to the feature-packs.
13. Stability Level
A level of stability can be associated to features and packages.
Stability levels are ordered in the following way:
default
(the higher level of stability) > community
> preview
> experimental
(the lower stability level)
A feature-pack can contain features and packages at different level of stability, allowing to provision installations at different stability levels.
13.1. Default stability levels
When building a feature-pack, the <feature-pack>
XML element contained in the feature-pack.xml
descriptor can include attributes to specify
the default stability levels that will be enabled when using the feature-pack during provisioning.
If no such stability levels exist, default
level is assumed.
The stability attributes are:
-
config-stability-level="<default|community|preview|experimental>"
attribute is used to declare the default stability level of the features present in the provisioned configurations. -
package-stability-level="<default|community|preview|experimental>"
attribute is used to declare the default stability level of the provisioned packages.
13.2. Stability levels can be overridden at provisioning time
It is possible to control the expected level of stability at provisioning time by means of the following Galleon options:
-
config-stability-level=<default|community|preview|experimental>
: To enable a given stability level for the provisioned configurations. -
package-stability-level=<default|community|preview|experimental>
: To enable a given stability level for the provisioned packages. -
stability-level=<default|community|preview|experimental>
: An option to enable both configs and packages stability levels. It can’t be set whenconfig-stability-level
orpackage-stability-level
are set.
14. Maven plugin
The Maven plugin allows to install a specific feature-pack into a new location or an existing installation or provision an installation the consists of multiple feature-packs.
The coordinates of the Maven plugin are
<dependency>
<groupId>org.jboss.galleon</groupId>
<artifactId>galleon-maven-plugin</artifactId>
<version>6.0.0.Final</version>
</dependency>
Installs a feature-pack into an empty directory or into an existing installation |
|
Provisions an installation that consists of one or more feature-packs at a specified location |
Unresolved directive in maven-plugin/index.adoc - include::../../../maven-plugin/target/generated-sources/plugin/install-feature-pack-mojo.adoc[]
14.1. provision
14.1.1. galleon:provision
Full name: org.jboss.galleon:galleon-maven-plugin:6.0.0.Final:provision
14.1.2. Description
This maven plugin provisions an installation that consists of one or more feature-packs. If the target installation directory already contains an installation, the existing installation will be fully replaced with the newly provisioned one. <p>In other words, the configuration provided for this goal fully describes the state of the final installation.</p>
14.1.3. Attributes
-
Requires a Maven project to be executed.
-
Requires dependency resolution of artifacts in scope:
compile+runtime
. -
Binds by default to the lifecycle phase:
process-test-resources
.
Name |
Type |
Since |
Description |
|
|
A list of feature-pack configurations to install. |
|
|
|
The target installation directory. |
Name |
Type |
Since |
Description |
|
|
A list of custom configurations to install. |
|
|
|
Path to a file containing |
|
|
|
Whether to log provisioning time at the end |
|
|
|
Whether to use offline mode when the plugin resolves an artifact.
In offline mode the plugin will only use the local Maven repository
for an artifact resolution. |
|
|
|
Arbitrary plugin options. |
|
|
|
Whether to record provisioned state in .galleon directory. |
|
|
|
A list of artifacts and paths pointing to feature-pack archives
that should be resolved locally without involving the
universe-based feature-pack resolver at provisioning time. |
|
|
|
Specifies whether the provisioning should be skipped. |
14.1.4. Parameter Details
-
Type:
java.util.List
-
Required:
No
-
Alias:
configurations
-
Type:
java.io.File
-
Required:
No
-
Alias:
custom-config
-
Type:
java.util.List
-
Required:
Yes
-
Alias:
feature-packs
-
Type:
java.io.File
-
Required:
Yes
-
Alias:
install-dir
-
Type:
boolean
-
Required:
No
-
Default:
false
-
Alias:
log-time
offline
Whether to use offline mode when the plugin resolves an artifact.
In offline mode the plugin will only use the local Maven repository
for an artifact resolution.
-
Type:
boolean
-
Required:
No
-
Default:
false
-
Alias:
offline
-
Type:
java.util.Map
-
Required:
No
-
Alias:
plugin-options
-
Type:
boolean
-
Required:
No
-
Default:
true
-
Alias:
record-state
resolveLocals
A list of artifacts and paths pointing to feature-pack archives
that should be resolved locally without involving the
universe-based feature-pack resolver at provisioning time.
-
Type:
java.util.List
-
Required:
No
-
Alias:
resolve-locals
-
Type:
boolean
-
Since:
4.2.6
-
Required:
No
-
User Property:
galleon.skip
-
Default:
false
Name |
Required |
Default value |
Description |
groupId |
yes |
- |
Feature-pack Maven artifact groupId. |
artifactId |
yes |
- |
Feature-pack Maven artifactId. |
version |
no |
- |
Feature-pack artifact version (if not specified the feature-pack must be a transitive dependency of a feature-pack with the version specified. |
inherit-configs |
no |
true |
Whether to inherit the default feature-pack configs |
included-configs |
no |
- |
Default feature-pack configs that should be included. |
excluded-configs |
no |
- |
Default feature-pack configs that should be excluded. |
inherit-packages |
no |
true |
Whether to inherit the default feature-pack packages. |
included-packages |
no |
- |
Default feature-pack packages that should be included. |
excluded-packages |
no |
- |
Default feature-pack packages that should be excluded. |
Example
<plugin>
<groupId>org.jboss.galleon</groupId>
<artifactId>galleon-maven-plugins</artifactId>
<executions>
<execution>
<goals>
<goal>provision</goal>
</goals>
<configuration>
<install-dir>${project.build.directory}/${project.build.finalName}</install-dir>
<feature-packs>
<feature-pack>
<groupId>org.wildfly.core</groupId>
<artifactId>wildfly-core-galleon-pack</artifactId>
<inherit-configs>false</inherit-configs>
<excluded-packages>
<name>product.conf</name>
<name>docs.schema</name>
</excluded-packages>
</feature-pack>
<feature-pack>
<groupId>${project.groupId}</groupId>
<artifactId>wildfly-servlet-galleon-pack</artifactId>
<version>${project.version}</version>
<excluded-packages>
<name>product.conf</name>
<name>docs.schema</name>
</excluded-packages>
</feature-pack>
</feature-packs>
<plugin-options>
<jboss-maven-dist/>
</plugin-options>
</configuration>
</execution>
</executions>
</plugin>
14.2. provision-file
14.2.1. galleon:provision-file
Full name: org.jboss.galleon:galleon-maven-plugin:6.0.0.Final:provision-file
14.2.2. Description
This maven plugin provisions an installation from a provisioning.xml file. If the target installation directory already contains an installation, the existing installation will be fully replaced with the newly provisioned one.
14.2.3. Attributes
-
Requires a Maven project to be executed.
-
Requires dependency resolution of artifacts in scope:
compile+runtime
. -
Binds by default to the lifecycle phase:
process-test-resources
.
Name |
Type |
Since |
Description |
|
|
The target installation directory. |
|
|
|
Path to a provisioning file located inside the current maven
project used to provision the server. |
Name |
Type |
Since |
Description |
|
|
Whether to log provisioning time at the end |
|
|
|
Whether to use offline mode when the plugin resolves an artifact.
In offline mode the plugin will only use the local Maven repository
for an artifact resolution. |
|
|
|
Arbitrary plugin options. |
|
|
|
Whether to record provisioned state in .galleon directory. |
|
|
|
Specifies whether the provisioning should be skipped. |
14.2.4. Parameter Details
-
Type:
java.io.File
-
Required:
Yes
-
Alias:
install-dir
-
Type:
boolean
-
Required:
No
-
Default:
false
-
Alias:
log-time
offline
Whether to use offline mode when the plugin resolves an artifact.
In offline mode the plugin will only use the local Maven repository
for an artifact resolution.
-
Type:
boolean
-
Required:
No
-
Default:
false
-
Alias:
offline
-
Type:
java.util.Map
-
Required:
No
-
Alias:
plugin-options
provisioningFile
Path to a provisioning file located inside the current maven
project used to provision the server.
-
Type:
java.io.File
-
Required:
Yes
-
Alias:
provisioning-file
-
Type:
boolean
-
Required:
No
-
Default:
true
-
Alias:
record-state
-
Type:
boolean
-
Since:
4.2.6
-
Required:
No
-
User Property:
galleon.skip
-
Default:
false
15. Galleon CLI tool
This command line tool (bin/galleon.[sh|bat]) allows you to provision/manage any products/installations that comply with galleon feature-packs.
Although being a generic tool, a builtin support is offered for products available from maven jboss community universe (eg: wildfly).
Possible actions that you can operate from the tool: install, uninstall, check for updates, patch, update, undo last provisioning command.
Launching the tool without any argument starts an interactive shell. Type exit to exit the tool.
Launching the tool with a command as argument will execute the command and exit, eg: galleon.sh install wildfly-core:current --dir=myinstallation
Launching the tool with --file=<path to script file> will execute the set of commands and exit.
Launching the tool with --help will display the descriptions of all available options and commands.
15.1. Feature-pack
A key concept in galleon system is the notion of feature-pack. A feature-pack is a content container. It can be a full product (eg: wildfly)
or part of a product (eg: a wildfly subsystem packaged as a feature-pack). With the tool you are going to install/uninstall/update/… feature-packs.
NB: A galleon installation can be composed of 1 or more feature-packs.
A feature-pack can be a file on your local file system or located inside a universe (a product catalog).
The tool helps you identify the feature-pack that you can use for the task you want to achieve. In order to take benefit of the full capabilities offered by the tool, one needs to understand how products are identified inside a universe.
15.2. Universe feature-pack location (FPL)
A feature-pack location (FPL) is the way to identify a product inside a universe without actually expressing any build numbers. A lot to commands require that you provide FPL.
The main (non exhaustive) FPL syntax is: <product>[@universe]:[version]/[qualifier]
Some examples of FPL to identify wildfly products:
-
wildfly:current =⇒ Final (released) wildfly product current version
-
wildfly:current/alpha =⇒ The latest release of wildfly product current version that is at least of alpha quality.
The things to notice:
-
Universe (from where the product comes from) is optional for products located in jboss maven community universe.
-
No actual version nor build (eg: 1.0.0-Alpha1-SNAPHOT) is provided. The syntax of FPL is abstract it allows you to express a level of expected quality without hard-coding any version number.
-
Pointed by an FPL is an actual feature-pack artifact (a zipped file) that the tool will download/install,…
-
A completer helps you compose FPL when the command you are calling expect one (eg: install).
For example, if one installs wildfly product using the following command:
install wildfly:current/alpha --dir=myInstallation
Then, later, when checking for updates or upgrading myInstallation directory, the latest build that is at least of quality alpha will be used to update. If a final release is available then it will be installed when upgrading.
NB: Products being unique inside an installation, some commands (eg: state update) only require the product part (<product>[@universe]) of an FPL. For example:
update --feature-packs=wildfly
15.3. Universe feature-pack id (FPID)
A feature-pack id (FPID) is the way to identify a product inside a universe by expressing a build number. This is the syntax to use when you want to deal with specific builds of a product.
The FPID syntax is: <product>[@universe]:[version]#[buildID]
Some examples of FPID to identify wildfly products:
-
wildfly:current#1.0.0-Final
-
wildfly:current#1.0.0-Alpha1
The things to notice:
-
Universe (from where the poduct comes from) is optional for products located in jboss maven community universe.
-
Pointed by an FPID is an actual feature-pack artifact (a zipped file)
-
A completer helps you compose your FPID when the command you are calling expect one (eg: install).
For example, to retrieve the informations of alpha1 build:
feature-pack get-info wildfly:current#1.0.0-Alpha1
15.4. Listing latest available feature-packs
[/]$ list-feature-packs [--all-frequencies] [--universe=<universe id>]
This command lists all the final feature packs present in all the installed universes.
The command looks in the current directory and its parent hierarchy for a possible installation
in which some universes would have been added. By default the builtin universe is used.
If --all-frequencies option is set, then the latest build of all frequencies are displayed.
If --universe option is set, the command lists the feature packs of this universe.
The information displayed by this command can be re-used when installing, updating features-packs. |
15.5. Searching for feature-packs
[/]$ find <pattern> [--universe=<universe id>] [--resolved-only]
This command searches for all the feature pack builds present in all the installed
universes that match the provided pattern.
The command looks in the current directory and its parent hierarchy for a possible installation
in which some universes would have been added. By default the builtin universe is used.
If --universe option is set, the command searches for feature packs inside this universe.
If --resolved-only option is set, the command only searches for feature packs installed in local repositories.
The information displayed by this command can be re-used when installing, updating features-packs. |
15.6. Installing a feature-pack
install <[FPL|FPID] | [--file=<path to fp zip file>]> [--dir=<installation dir>] [--verbose] [feature-pack specific options]
This creates a directory containing the installed feature-pack content (binaries, configs).
NB: Using completion, when an installation directory has been identified, the options that are specific to the feature-pack to install are proposed. When installing for the first time a feature-pack this can take some time (a matter of few seconds up to minutes if the feature-pack needs to be downloaded from a remote location).
You can retrieve the set of feature-pack specific options without relying on completion, to do so call:
feature-pack get-info <[FPL|FPID] | [--file=<path to fp zip file>]> --type=options
You can then use the listed options (if any) to customize your install command.
15.7. Installing a subset of feature-pack configurations
When installing a feature-pack, all its default configurations are installed. Use the --default-configs=<comma separated list of config_model/config_name> option to specify the subset of configurations to install.
15.8. Installing feature-pack layers
The install command can be used to install a subset of feature-pack features. Such subset are called layers. When installing layers, a custom configuration is generated.
install <[FPL|FPID] | [--file=<path to fp zip file>]> [--dir=<installation dir>] [--layers=<comma separated list of layers>] [--config=<layers_model/configuration_name>]
In order to exclude an optional layer on which a layer from the list depends on, prefix the excluded layer with '-'. In order to un-exclude a layer already excluded in the current installation, prefix the layer with '+'.
NB: When installing layers, the existing provisioned installation (if any) is updated with the set of layers.
-
If some layers to install are already installed, they are ignored.
-
If some layers to exclude are already excluded, they are ignored.
-
If some layers to install are excluded from the existing installation, they are first un-excluded and installed.
-
If some layers to exclude are included in the existing installation, the command will fail. You can only exclude not directly included layers.
-
If some layers to un-exclude are not excluded, the command will fail.
-
If some layers to exclude are not optional dependencies of the layers to install (or from already installed layers), the command will fail. You can only exclude layers that are optional dependencies.
If no model name is provided, the CLI tries to identify the default model contained in the feature-pack. If no configuration name is provided, the <layers_model>.xml is used as the generated configuration file name.
You can retrieve the set of feature-pack defined layers without relying on completion, to do so call:
feature-pack get-info <[FPL|FPID] | [--file=<path to fp zip file>]> --type=layers
You can then use the listed layers (if any) to customize your install command.
15.9. Un-installing a feature-pack
uninstall [FPID] [--dir=<installation dir>] [--verbose] [feature-pack specific options]
This will remove the content installed by the feature-pack identified by the FPID. Some feature-pack specific options can be provided, they will be used when re-provisioning the remaining (if any) feature-packs.
NB: Completer proposes the FPID you can un-install from the installation (products and patches). Completion of feature-pack specific options are handled the same way as in the install command.
15.10. Un-doing the last provisioning command
undo [--dir=<installation dir>] [--verbose]
This will revert the installation to the previous installed state.
15.11. Patching an installation
Use the install command to patch an existing installation.
install <[FPL|FPID] | [--file=<path to patch zip file>]> [--dir=<installation dir>] [--verbose] [feature-pack specific options]
15.12. Un-installing a patch
Use the uninstall command to remove a given patch or use state undo if the last provisioning command has been a patch installation.
15.13. Checking for updates
check-updates [--dir=<installation dir>] [--include-all-dependencies] [--feature-packs=<list of feature-pack producers>]
If no products are provided, all installed products are checked for updates.
15.14. Updating an installation
The update command allows to update an installation to the latest available versions of installed feature-packs.
update [--dir=<installation dir>] [--include-all-dependencies] [--yes] [--feature-packs=<list of feature-pack producers or locations>] [feature-pack specific options]
Display the list of available updates/patches then update. If --yes is provided, the command will proceed without asking for confirmation.
NB: If the option --feature-packs contains feature-pack locations with versions, then these versions are used to update the feature-packs.
NB: Using completion, when an installation directory has been identified, the options that are specific to the installed feature-pack(s) are proposed. When updating an installation for the first time this can take some time (a matter of few seconds up to minutes if the feature-pack needs to be downloaded from a remote location).
You can retrieve the set of feature-pack specific options without relying on completion, to do so call:
installation get-info [--dir=<installation dir>] --type=options
You can then use the listed options (if any) to customize your update command.
15.15. Retrieving changes applied to an installation
In order to visualize files you have added, removed or modified, use the command get-changes [--dir=<installation>].
In the CLI output added files are prefixed by '+', removed ones by '-' and modified ones by 'M'.
15.16. Persisting changes applied to an installation
Installed feature-packs optionally support persistence of changes into the provisioning configuration. As an example, wildfly feature-packs persist configuration changes into the provisioning config.
Use the command persist-changes [--dir=<installation>] to persist the changes.
NB: If the installed feature-packs don’t support the ability to merge changes into the provisioning configuration, this operation has no side effect.
15.17. Observing an installation
[my-dir]$ installation get-info [--dir=installation] --type=[all|configs|dependencies|layers|optional-packages|options|patches|universes]
Display the set of installed feature-packs FPID. In addition can display configurations, dependencies layers and patches.
NB: If some patches are applied, the applied patches information is displayed.
15.18. Observing a feature-pack
[my-dir]$ feature-pack get-info <[FPL|FPID] | [--file=<path to fp zip file>]> --type=[all|configs|dependencies|layers|optional-packages|options]
Display the FPID of a feature-pack. In addition can display dependencies, configurations, layers and options usable when installing/provisioning/upgrading.
15.19. Optional packages
When getting information on an installation or a feature-pack, using --type=optional-packages option, you can retrieve the list of optional packages. At installation time the set of optional packages installed is controlled by the option --optional-packages=<all|none|passive|passive+>.
There are 2 kind of optional packages. passive ones, that are installed only if all their dependencies are installed and optional ones that have no requirements on their dependencies. Generally passive optional packages shouldn’t be excluded from an installation. They are needed for the package to properly operate when the other packages on which it depends are provisioned. Optional packages that are not passive can be excluded if not needed (according to the execution context).
When installing a complete feature-pack or installing a default configuration, the default value for --optional-packages is all (all optional and passive packages are installed).
When installing layers with the install commands the default value for --optional-packages is passive+ (all optional and passive packages that have all their dependencies installed are installed).
You can override these default values by using the --optional-packages option. Use none value to not install any optional nor passive packages, passive value to only install passive packages that have all their dependencies installed.
15.20. Managing the local cache of feature-packs
When a feature-pack is internally resolved (at install time, to expose information, to retrieve plugin options, …). The feature-pack is added to a local cache. This cache is re-used to speed-up future resolutions. The CLI cleanup un-used feature-pack from the cache that are older than one month.
You can import (and optionally install in the universe for later resolution) a feature-pack zip file in the cache.
[my-dir]$ feature-pack import <path to fp zip file> [--install-in-universe=<true|false>]
You can clear the cache fully (NB: this will have a performance impact for future resolution).
[my-dir]$ feature-pack clear-cache
15.21. Exporting an installation to xml
[my-dir]$ installation export <new generated xml file> --dir=<installation>
15.22. Provisioning an installation from xml
[my-dir]$ provision <xml file> --dir=<target installation directory> [feature-pack specific options]
NB: Using completion, when an installation directory has been identified, the options that are specific to the feature-pack(s) located in the XML configuration file are proposed. When provisioning an installation for the first time this can take some time (a matter of few seconds up to minutes if the feature-pack needs to be downloaded from a remote location).
15.23. Managing the history of an installation
By default the history keeps the state of the last 100 provisioning operations. This should be enough to cover
simple undo of provisioned state. Nevertheless you can increase/decrease this
value by using the following command:
installation set-history-limit <history size limit> [--dir=<installation dir>]
To retrieve the history size limit do:
installation get-history-limit [--dir=<installation dir>]
15.24. Managing installation universes
A universe can be added/removed to/from an existing installation.
Add a named or default (without using the --name option) universe to an installation.
[/]$ installation add-universe [--dir=<installation dir>] [--name=<universe name>] --factory=<universe factory> --location=<universe location>
Remove a named or default (without using the --name option) universe from an installation.
[/]$ installation remove-universe [--dir=<installation dir>] [--name=<universe name>]
15.25. Directory option
Some commands (eg: install, get-info, check-updates, …) allow you to optionally provide a target directory thanks to the --dir=<path> option. If no directory is provided, the command will lookup for an existing installation in the current directory (that you can change with the cd command) and its parent directories hierarchy. If no installation exists, the command will abort.
There are some exceptions to this installation lookup. install and provision commands expect the current directory to be empty or to be the root of an installation. uninstall, undo and update commands expect the current directory to be the root of an installation.
15.26. Exploring an installation or a feature-pack.
The tool allows you to switch to a state edit mode in which you can observe and edit a provisioning state in memory (without actually impacting the installation files).
To explore an installation:
[my-dir]$ state edit [<installation dir>]
[!edit!my-dir!/]$
After this point, the tool switched to edit mode with a set of new commands available.
Type help to list the set of available commands in this mode. |
To explore a feature-pack:
[my-dir]$ state new
[!edit!/]$ add-dependency <[FPL|FPID] --default-configs-inherit --packages-inherit
Once exploring, prompt, ls, cd and pwd commands are bound to the feature-pack (or installation) exposed file-system.
Use leave-state to switch the tool back to its nominal mode.
[!edit!/]$ ls
configs
dependencies
feature-specs
packages
[!edit!/]$ leave-state
[my-dir]$
The fs is composed of:
/configs/final/<model>/<name>/<features>
/feature-specs/<origin>/<feature-specs>
/packages/<origin>/<packages>
Features and feature-specs are organized as a file system with containment.
Use ‘ls’ to visualize any item. Use ‘cd’ to navigate to a given node. |
15.27. Searching the current state
When in edit mode, one can search for packages and features.
[!edit!/]$ search [--query=<some text> | --package=<package name>]
When searching with --query all packages and features are looked-up for a match. If packages are matched, the features that depend directly or indirectly on these packages will be shown in the result.
When searching with --package, the package completer can be used. The features that depend directly or indirectly on this package will be shown in the result.
15.28. Creating a new state (or editing an existing state from an installation or provisioning XML file)
This allow to start from an empty installation or re-use an installation and iteratively add/suppress content.
[my-dir]$ state new | state edit <path to installation dir | path to provisioning XML file>
[!edit!/]$ ls
configs
dependencies
feature-specs
packages
NB: Each action as the effect to build a runtime with the current state. The filesystem reflects the current state.
NB: Each action applied to a state in edition can be undone: undo.
NB: Use leave-state to leave the edit mode.
NB: The set of completer exposed commands is dynamic and is adjusted according to the current state.
15.29. Exporting or provisioning the current state
In edit mode, one can export the provisioning XML file or directly provision from the current state:
[!edit!/]$ export [<path to generated xml file>]
[!edit!/]$ provision <dir of new installation>
Use export to validate that what you get in the XML is in sync with the expose state. |
Exporting a state without any XML target file will display the XML content in the CLI console. |
The command 'get-info' can be used to get high level information. |
15.30. Adding a feature-pack
[!edit!/]$ add-dependency <FPL|FPID> [--default-configs-inherit] [--packages-inherit]
By default nothing is inherited. Once at least one feature-pack has been added, configurations or packages can be handled.
15.31. Removing a feature-pack
[!edit!/]$ remove-dependency <FPL|FPID>
15.32. Including a default configuration
[!edit!/]$ include-config <model>/<name> [--origin=<fp origin>]
Origin is optional, by default will be included from all fp that expose it.
15.33. Removing an included default configuration
[!edit!/]$ remove-included-config <model>/<name> [--origin=<fp origin>]
The completer only proposes the set of configurations that have been previously included. Origin is optional, by default will be remove from all fp that include it.
15.34. Excluding a default configuration
[!edit!/]$ exclude-config <model>/<name> [--origin=<fp origin>]
Origin is optional, by default will be excluded from all feature-packs that expose it.
15.35. Removing an excluded default configuration
[!edit!/]$ remove-excluded-config <model>/<name> [--origin=<fp origin>]
The completer only proposes the set of configurations that have been previously excluded. Origin is optional, by default will be removed from all feature-packs that exclude it.
15.36. Including layers into a configuration
NB: Prior to be able to include layers into a configuration you need an included default or locally defined configuration. To define a new configuration call define-config --model=<config model> --name=<config name>
[!edit!/]$ include-layers <config model/config name> --layers=<comma separated list of layers>
NB: The completers for both configuration and layers propose you with the existing configurations and layers not already included.
15.37. Removing included layers from a configuration
[!edit!/]$ remove-included-layers <config model/config name> --layers=<comma separated list of included layers>
NB: You can only remove layers that have been explicitly included in your local configuration. Layers included in a default configuration can be excluded but their inclusion can’t be removed.
15.38. Excluding layers from a configuration
NB: Prior to be able to exclude layers from a configuration you need an included default or locally defined configuration that contain layers.
[!edit!/]$ exclude-layers <config model/config name> --layers=<comma separated list of layers>
NB: The completers for both configuration and layers propose you with the existing configurations and included layers.
15.39. Removing excluded layers from a configuration
[!edit!/]$ remove-excluded-layers <config model/config name> --layers=<comma separated list of excluded layers>
NB: You can only remove layers that have been explicitly excluded in your local configuration.
15.40. Reseting a configuration
[!edit!/]$ reset-config <model>/<name>
The custom content of this configuration is removed.
NB: This has no effect on included/excluded configurations.
15.41. Including a default package
[!edit!/]$ include-package <fp origin>/<package name>
15.42. Removing an included default package
[!edit!/]$ remove-included-package <package name> [--origin=<fp origin>]
The completer only proposes the set of packages that have been previously included. The origin is optional, the package will be removed from all feature-packs that exclude it.
15.43. Excluding a default package
[!edit!/]$ exclude-package <fp origin>/<package name>
15.44. Removing an excluded default package
[!edit!/]$ remove-excluded-package <package name> [--origin=<fp origin>]
The completer only proposes the set of packages that have been previously excluded. The origin is optional, the package will be removed from all feature-packs that exclude it.
15.45. Adding a new feature
[!edit!/]$ add-feature <config model/name> <path to feature-spec> <dynamic set of feature param=<value>>
For example:
add-feature standalone/standalone.xml org.wildfly.core:wildfly-core-galleon-pack/interface --interface=toto --inet-address=127.0.0.1
NB: All parameters are exposed as command option.
NB: All parameters that are not nillable and have no default values are required. The command being aborted if there are missing required parameters.
NB: If the parameter is not present, its default value is injected when creating the feature.
NB: The current location (thanks to cd) is not yet taken into account when completing/adding the feature. That is a TODO.
NB: A feature with the same feature-id can’t exist. A single feature with the given feature-id per config.
15.46. Removing a feature
[!edit!/]$ remove-feature <full path to feature inside a configuration>
For example:
remove-feature standalone/standalone.xml/interface/toto
15.47. Managing universes
A universe can be added/removed to/from a state.
Add a named or default (without using the --name option) universe to the state.
[!edit!/]$ add-universe [--name=<universe name>] --factory=<universe factory> --location=<universe location>
Remove a named or default (without using the --name option) universe from the state.
[!edit!/]$ remove-universe [--name=<universe name>]
16. CLI tool Maven configuration
By default the following maven repositories are used to retrieve FP.
The cli allows you to change the path to the local repository and add/remove remote maven repositories.
16.1. Relying on maven settings
In order to makes the cli to use a maven settings file call: maven set-settings-file <path to settings xml file>
In order to remove the reference to the settings file call: maven reset-settings-file
NB: Advanced mirroring (eg: external:*) is not supported.
NB: Any other cli maven configuration items will be overridden when a settings xml file is set.
NB: If no local repository is set in settings file, the local repository (default or configured) is used.
The following default repositories are enabled if not already present in the enabled profiles:
-
maven-central
:https://repo1.maven.org/maven2/
-
jboss-public-repository-group
:https://repository.jboss.org/nexus/content/groups/public/
-
jboss-ga
:https://maven.repository.redhat.com/ga/
NB: These default repositories can be mirrored by using their ids.
16.2. Adding new remote repositories
Use the following command to add new remote repositories:
maven add-repository --name=myrepo --url=http://foorepo [--release-update-policy=<policy>]
[--snapshot-update-policy=<policy>] [--type=<type>] [--enable-release=[true|false] [--enable-snapshot=[true|false]
NB: The type, release update policy, snapshot update policy and enable/disable of snapshot/release are optional and have default values.
16.3. Default Repository policies
Daily update for releases, never update for snapshots.
Warn if checksum differs.
Snapshots are not resolved from remote repositories.
Releases are resolved from remote repositories.
Update polices can be changed by calling:
maven set-release-update-policy [<always|daily|interval:|never>]
maven set-snapshot-update-policy [<always|daily|interval:|never>]
Activation of snapshot/release resolution can be changed by calling:
maven enable-snapshot [<true|false>]
maven enable-release [<true|false>]
NB: A reset command can be called for any of these changes to set the value back to its default value.
16.4. Advanced maven configuration
Proxy, authentication and mirroring are only supported when setting a maven xml settings file.
16.5. Local repository
By default the local maven repository is located in <user.home>/.m2/repository.
You can change this directory by using the command: maven set-local-repository <path to your local repository directory>
In order to reset to the default local maven repository call: maven reset-local-repository
16.6. Offline mode
By default maven is in online mode. In order to switch to offline use the command maven enable-offline <true|false>
In order to reset to the default mode call: maven reset-offline
16.7. Display maven configuration
Call command: maven get-info
16.8. Impact on Universe
Any change made to the maven configuration makes the CLI to re-resolve universe(s). This means that stream resolution stays in sync with maven configuration.
16.9. Resolving feature-packs
When remote repositories are set, feature-packs are automatically downloaded at install time. You can download feature-pack explicitly to the local repository by using the command: maven resolve-feature-pack <feature-pack location> [--verbose]
16.10. Maven tracing
When enabling "verbose" at installation and provisioning time, any artifact retrieved from a remote repository is advertised in the console. This also applies when fetching explicitly feature-packs.