© 2018 The original authors.

1. Overview

Galleon is a Maven repository-based Java provisioning tool designed to manage software installations that consist of one or more products. The tool supports:

  • installation of products;

    • their default and customized configurations;

  • integration of the installed products;

  • resolution and verification of configuration and runtime dependencies;

  • patching and version updates;

  • product-specific provisioning plugins;

  • identification of the changes to the provisioned software (the FS content and/or the configuration) applied manually or using thirdparty tools;

  • export the current environment configuration 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 provisions an installation according to the configuration.

2. Feature-packs

Feature-pack represents a released unit of software that can be installed or uninstalled using the provisioning tool. Feature-packs are Maven artifacts identified by GAV (groupId, artifactId and version).

Feature-pack contains:

  • metadata describing

    • dependencies on other featurepacks;

    • the default configuration(s) of the distribution;

    • the default package set that should be installed;

  • (optional) a set of content packages;

  • (optional) a set of configuration features;

  • (optional) various resources required to properly assemble and setup the installation;

  • (optional) custom 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 (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
|- feature_groups/
|- features/
|- packages/
|- plugins/
|- resources/
`- feature-pack.xml

Where

  • feature_groups - optional directory containing feature group descriptions;

  • features - optional directory containing feature specs (configuration units);

  • packages - optional directory containing packages (units of filesystem content);

  • resources - optional directory containing various resources needed to properly setup the installation;

  • plugins - optional directory containing product-specific provisioning plug-ins;

  • feature-pack.xml - metadata describing the feature-pack and the default distribution.

2.2. Feature-pack metadata (feature-pack.xml)

Feature-pack metadata contains the following information:

  • GAV - feature-pack groupId, artifactId and version;

  • (optional) dependencies - dependencies on other feature-packs.

  • (optional) config - config elements describe the default configurations generated for the installation (there could be more than one default configuration);

  • (optional) default packages - the names of the packages that are installed by default.

Here is an illustration of how it may look like in a feature-pack.xml file:

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
                groupId="org.my-group"
                artifactId="my-artifact"
                version="1.0.0.Alpha1">
    <dependencies>
        <dependency groupId="org.another-group"
                    artifactId="another-artifact"
                    version="3.0.0.Final"/>
    </dependencies>
    <config>
        <props>
            <prop name="prop1" value="value1"/>
            <prop name="prop2" value="value2"/>
        </props>
        <feature-group name="group1"/>
        <feature spec="feature1">
            <param name="p1" value="v1" />
            <param name="p2" value="v2" />
        </feature>
    </config>
    <default-packages>
        <package name="package1"/>
        <package name="package2"/>
    </default-packages>
 </feature-pack>

In this example:

  • feature-pack org.my-group:my-artifact:1.0.0.Alpha1 depends on feature-pack org.another-group:another-artifact:3.0.0.Final;

  • config element describes the default configuration that will be generated;

  • packages package1 and package2 are installed by default.

3. General provisioning workflow

This is not a precise description of how it happens but a high level overview of the workflow.

  1. The provisioning mechanism determines a set of feature-packs that need to be resolved for the installation

  2. Feature-pack version compatibility is checked

  3. The feature-packs are downloaded from their respective repositories and unpacked in a temporary location

  4. 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

  5. A staged directory is created

  6. Content from all the feature-pack packages is copied to the staged directory (in the order the feature-packs should be installed)

  7. 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

  8. The provisioned state of the installation is recoded

  9. The installation created in the staged directory is moved to the target installation directory (fully replacing the current one, if it exists)

  10. The temporary directories are deleted

4. Provisioning FS content

In a feature-pack, the file system content of the distribution is organized into packages. What is provisioned content-wise at the end depends on which packages were selected for the target installation.

4.1. Feature-pack packages

A package is a minimal atomic unit of a file system 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 and used by the provisioning tool to provision a piece of an FS content.

Essentially, a software release (FS 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.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 the 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.1.2. Package metadata (package.xml)

Package metadata contains the following information:

  • package name;

  • (optional) dependencies - dependencies on other packages from the same or other feature-packs;

Here is an illustration of how a package.xml might look like:

 <package-spec xmlns="urn:jboss:galleon:package:1.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 the alias another-feature-pack.

4.1.3. Package dependencies

Package dependency may be required or optional.

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 the examples, the rest of the 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:1.0" name="p1">
    <dependencies>
        <package name="p2"/>
        <package name="p3" optional=”true”/>
    </dependencies>
 </package-spec>

In this example p2 is a required dependency of p1 while p3 is an optional one.

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 the 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.1.4. 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:1.0"
                groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0">
    <dependencies>
        <dependency groupId="org.jboss.pm.test" artifactId="fp2" version="2.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:1.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.2. Provisioned package set

This chapter is dedicated to the effective (resolved) package set of an installation.

4.2.1. Feature-pack without dependencies

This chapter focuses on a single feature-pack without dependencies. Effective package set of feature packs with dependencies will be covered in a separate chapter.

Feature-pack default packages

Feature pack may define a set of default packages. This set of default packages is installed implicitly when the feature-pack is installed unless the user provides explicit instructions which packages to install.

Default packages are explicitly listed in the feature-pack.xml file which is a part of the feature-pack archive. For example:

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
                groupId="org.jboss.fp.group1" artifactId="fp1" version="1.0.0" >
    <default-packages>
        <package name="package1" />
        <package name="package2" />
    </default-packages>
 </feature-pack>

In case 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.

Feature-pack non-default packages

Feature-pack may contain packages that are not marked as default in the feature-pack.xml. Non-default packages can be installed either:

  • implicitly, in case a default package declared a dependency on a non-default package or the non-default package appears as a transitive dependency of a default package;

  • explicitly, in case a user explicitly selected a non-default package to be installed.

Feature-pack original effective package set

Original in the title means not explicitly modified. I.e. a set of packages which is going to be installed when a feature-pack is installed as-is without any user customization.

The feature-pack’s original effective package set consists of all the default packages of the feature-pack plus all the packages from the package dependency trees originating from the default packages.

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 xmlns="urn:jboss:galleon:feature-pack:1.0"
                groupId="org.jboss.fp.group1" artifactId="fp1" version="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 package p11

  • package p2 has an optional dependency on non-default package p22

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

 <feature-pack groupId="org.jboss.group1" artifactId="fp1" version="1.0.0">
    <packages>
        <exclude name="p11"/>
        <exclude name="p2"/>
    </packages>
 </feature-pack>

Packages p11 and p2 are explicitly excluded and package p22 is a non-default package which is not on the dependency tree originating from the packages to be installed, i.e. p1.

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 xmlns="urn:jboss:galleon:feature-pack:1.0"
                groupId="org.jboss.fp.group1" artifactId="fp1" version="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 package p21

  • fp1 also contains non-default package p3

  • p3 has an optional dependency on non-default package p31

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:

 <feature-pack groupId="org.jboss.group1" artifactId="fp1" version="1.0.0">
    <packages>
        <include name="p3"/>
        <exclude name="p2"/>
        <include name="p21"/>
    </packages>
 </feature-pack>

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

 <feature-pack groupId="org.jboss.group1" artifactId="fp1" version="1.0.0">
    <packages>
        <exclude name="p1"/>
        <exclude name="p2"/>
        <include name="p21"/>
        <include name="p3"/>
        <exclude name="p31"/>
    </packages>
 </feature-pack>

4.2.2. Feature-pack with dependencies

Feature pack may depend on one or more other feature-packs. Feature-pack dependencies are expressed in the feature-pack metadata, i.e. the feature-pack.xml file. For example:

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
                groupId="org.jboss.fp.group1" artifactId="fp1" version="1.0.0" >
    <dependencies>
        <dependency groupId="org.jboss.dep.group1" artifactId="fp2" version="0.0.1"/>
        <dependency groupId="org.jboss.dep.group2" artifactId="fp3" version="0.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. Let’s also assume that fp3 depends on feature-pack fp4 and fp2 and fp4 don’t have any further dependencies. The effective package set of feature-pack fp1 will consist of:

  • the original effective package set of fp1;

  • the original effective package set of fp2;

  • the original effective package set of fp3;

  • the original effective package set of fp4.

Customizing the inherited package set from a dependency

As shown in the example above, the effective package set of the dependency contributes to the effective package set of the feature-pack declaring the dependency. The feature-pack declaring the dependency, though, is allowed to customize the package set inherited from the dependency using the already seen before include and exclude XML elements in its feature-pack.xml. For example:

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
                groupId="org.jboss.fp.group1" artifactId="fp1" version="1.0.0" >
    <dependencies>
        <dependency groupId="org.jboss.fp.group2" artifactId="fp2" version="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>

Package inclusion and exclusion under the dependency element in feature-pack.xml file follows the same principle (and the syntax) as it was described for the provisioning XML configuration file.

Now the original effective package set of fp1 becomes:

  • fp1 packages p1 and p2;

    • plus their dependencies on non-default packages (if any);

  • the original effective package set of fp2;

    • minus packages p1 and p2 from fp2 and their dependencies on other packages;

    • plus packages p3 and p4 from fp2 and their dependencies on other packages.

Note: in case fp2 in its turn depended on other feature-packs then fp1 would inherit effective package sets of those feature-packs (possibly customized using include/exclude in the corresponding dependency declaration in the feature-pack.xml of fp2).
Disabling inheritance of a dependency package set

By default, 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 effective package set and simply pick the packages explicity under the dependency element (in other words to explicitly define the effective package set of the dependency).

Optional boolean attribute inherit on the packages element controls whether the inheritance is enabled or disabled. In case the attribute is not explicitly specified, its value assumed to be true. Here is an example of a dependency with the inheritance disabled:

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
                groupId="org.jboss.fp.group1" artifactId="fp1" version="1.0.0" >
    <dependencies>
        <dependency groupId="org.jboss.fp.group2" artifactId="fp2" version="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>

Now the original effective package set of fp1 becomes:

  • fp1 packages p1 and p2;

    • plus their dependencies on non-default packages (if any);

  • fp2 packages p3 and p4;

    • plus their dependencies on non-default packages minus packages p1 and p2 from fp2 and their dependencies on other packages.

Merging package sets from dependency branches

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 custom package sets of fp4 specified as dependencies of fp2 and fp3.

For example:

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
                groupId="org.jboss.fp.group1" artifactId="fp1" version="1.0.0" >
    <dependencies>
        <dependency groupId="org.jboss.fp.group2" artifactId="fp2" version="2.0.0"/>
        <dependency groupId="org.jboss.fp.group2" artifactId="fp3" version="2.0.0"/>
    </dependencies>
    <default-packages>
        <package name="p1"/>
    </default-packages>
 </feature-pack>
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
                groupId="org.jboss.fp.group1" artifactId="fp2" version="1.0.0" >
    <dependencies>
        <dependency groupId="org.jboss.fp.group2" artifactId="fp4" version="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:1.0"
                groupId="org.jboss.fp.group1" artifactId="fp3" version="1.0.0" >
    <dependencies>
        <dependency groupId="org.jboss.fp.group2" artifactId="fp4" version="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:1.0"
                groupId="org.jboss.fp.group1" artifactId="fp4" version="1.0.0" >
    <default-packages>
        <package name="p1"/>
        <package name="p2"/>
        <package name="p3"/>
    </default-packages>
 </feature-pack>

If a user installs fp1 without further customizations, the following packages will be installed:

  • fp1:p1 and its dependencies;

  • fp2:p1 and its dependencies;

  • fp3:p1 and its dependencies;

  • fp4:p2, fp4:p4 and their dependencies.

5. Provisioned installation configuration

In addition to provisioning the FS content the tool also supports generation of the configuration for the target installation taking into account the customizations of the feature-pack default settings applied by the user.

Feature-pack metadata (feature-pack.xml) may include one or more config elements each of which describes specific complete flavour of an distribution configuration. In a simple (and perhaps the most common) case, the configuration described under config element will represent a specific configuration file in the provisioned installation.

Installation configuration is described using a generic configuration model. The model allows a user to manipulate the confguration in a generic way by adding to and/or removing parts from it, overwriting existing values. The responsibility of the tool with regards to the configuration is to:

  • resolve the final installation configuration taking into account the customizations applied to the pre-configured default configuration;

  • make sure the resolved configuration is valid by:

    • verifying that the required configuration values are set;

    • verifying the referential integrity of the resolved configuration model (i.e. in case certain configuration units imply the presence of certain other configuration units);

  • 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 the configuration units.

The generic provisioning tool itself does not generate the final configuration files. As indicated above, it only resolves the effective generic configuration model for the provisioned installation. It is the responsibility of the product-specific provisioning plugins to generate the final configuration file(s) from the generic configuration model resolved by the core provisioning mechanism.

5.1. Generic configuration model

Generic configuration model is based on an abstract schema that describes configurable units and relationships between them.

5.1.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

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
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, where the unique_name is the value of parameter name of the corresponding 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.
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"/>
     <param name="b" default="bb"/>
     <param name="c" nillable="true"/>
     <param name="d"/>
   </params>
 </feature-spec>

In this spec

  • parameter a is a feature ID parameter, cannot be null and must be explicitly initialized in the configuration;

  • parameter b will have a default value of bb unless explicitly initialized;

  • parameter c has not default and may be left uninitialized in the configuration;

  • parameter d must be explicitly initialized in the configuration.

Features in a configuration

Here is an example of how features can be used in a configuration.

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
                groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0">
   <config>
     <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.

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 from another feature spec. In other words, a feature spec may declare certain parameters as references to other feature ID parameters. (In a relational database, this would be a foreign key reference).

In a feature spec a simple feature reference would look like

 <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 in the ref element contains a 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 implicit reference parameter mapping.

The implicit reference parameter mapping rule is based on the expectation that the feature spec declaring a 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:

  1. featureP declares parameter p and it is its only feature-id parameter;

  2. featureP declares parameter name and it is its only feature-id parameter;

  3. featureP declares parameters name and p and both of them are its only feature-id parameters.

Table 1. The complete set of a feature reference declaration attributes
Attribute name Required Default Description

dependency

false

null (current feature-pack)

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.

Custom reference parameter mapping

Suppose we want to explicitly map parameters in the reference declaration. 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's 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 origin of the external feature spec is specified in the dependency attribute of the feature reference declaration. The value of the dependency attribute must match the value of the name element of the feature-pack dependency (the referenced feature spec belongs to) declaration in the feature-pack.xml file.

For example, suppose, feature-pack fp1 depends on feature-pack fp2.

 <feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
                groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0">
    <dependencies>
        <dependency groupId="org.jboss.pm.test" artifactId="fp2" version="2.0.0">
            <name>fp2-dep</name>
        </dependency>
    </dependencies>
 </feature-pack>

fp2 includes a 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 a 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>
Implicit feature reference parameter initialization

Let’s suppose we have a parent-child relationship between two feature specs, e.g.

 <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>
   <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 the parentId parameter is set on every feature. There is a more compact way of expressing the same configuration using nesting, e.g.

 <config>
   <feature spec="featureP">
     <param name="parentId" value="parent1"/>
     <feature spec="featureC">
       <param name="childId" value="child1"/>
     </feature>
   </feature>
 </config>

As can be seen, the parentId parameter is initialized only once on the parent feature. The parentId of the child feature will be implicitly initialized to the value of the 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>
   <feature spec="featureP">
     <param name="parentId" value="parent1"/>
     <feature spec="featureC" parent-ref="parent">
       <param name="childId" value="child1"/>
     </feature>
   </feature>
 </config>
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 its configured default values. This is done by simply setting the 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 having a feature spec called link. The link must have an ID parameter, let it be called id. Then it has to include a parameter to reference to 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 won’t 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 resolve 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 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 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 grapth will be processed respecting the references.
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 the 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 the feature feature2:id=123 (inherited dependency from the spec) and the feature feature3:id=789.

External feature dependencies

If the feature3 spec was from another feature-pack than the feature1 spec then we’d have to add the origin of the feature3 spec to the dependency declaration. Assuming that the feature-pack the feature1 spec belongs to declared a dependecy named fp2 on the feature-pack the feature3 spec belongs to, the dependency declaration will 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 the include attribute. If the dependency is declared with the 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>
Feature capabilities

In the actual provisioned product, 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 two reasons why this may be important when resolving the configuration model for the installation to be provisioned:

  1. to make sure that the configuration is consistent in a sense that the runtime requirements of its components are satisfied;

  2. 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 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 that expresses a requirement on 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 constants. This type of a capability is called a static capability. As a consequence, all the features of the interface spec will provide the same capability org.wildfly.network.interface. And all the features of the socket-binding spec will require the same capabality org.wildfly.network.interface.
Dynamic capabilities

It is also possible, however, to provide 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 parameters names prefixed with the $ 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:1.0"
                groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0">
   <config>
     <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 the dot as a separator for the parameters and the static parts of the name.
Feature package dependencies

Feature specs representing configurable components of the installation may include dependencies on the feature-pack packages that contain the binaries of those installation components. So that, when a feature is included into a configuration, the packages it declared dependencies on will implicitly be added to the list of the installed packages.

Package dependencies are configured under the 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, a feature of the feature1 spec will have:

  • a required dependency on the package p1;

  • an optional dependency on the package p2;

  • a required dependency on the package p2 from the feature-pack dependency refered to as another-feature-pack;

  • an optional dependency on the package p3 from the feature-pack dependency refered to as another-feature-pack.

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 made 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>

5.1.2. Feature groups

A feature 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 later 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:1.0"
                groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0">
   <config>
     <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 the group1.

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"
                groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0">
   <config>
     <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.

  1. feature1:id=a1

  2. feature2:id=b1

  3. feature3:id=c1

  4. feature4:id=d1

Including customized feature groups

When a feature group is included (into another feature group or the config element of the 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:

When a feature group is included into another feature group or a config, 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 the feature-group XML element.

Overwriting parameters of features from a feature group

The configuration of a feature can be customized by adding the include element with the 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>
  <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 spec is

<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 the group1 into the config.

<config>
  <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 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 excluded:

<config>
  <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 the feature1 spec can be excluded:

<config>
  <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 group or a config, by default all the features it contains are included but it is also possible 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 config:

<config>
  <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 the include elements are picking the features that need to be included by their IDs.

The config will include feature1:id=a1 and feature2:id=b1.

The include elements can also be used to pick features from the excluded feature specs. The config below is equivalent to the config above.

<config>
  <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 included but it is also possible 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 feature1 can be included into the config:

<config>
  <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 the 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 spec 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>
  <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 the two features:

Feature spec parent

featureP

p1

Feature spec parent child a b

featureC

p1

c1

config

config

Including features and feature groups from other feature-packs

Feature groups, as well as config elements in the feature-pack.xml, may include features and feature groups from other feature-packs. This is done by including one or more feature-pack element and specifying the origin of the included features and feature groups in its dependency attribute. 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

  1. feature1:id=a1 from the local feature-pack;

  2. features from group2 from another-feature-pack;

  3. feature2:id=b1 from another-feature-pack;

  4. features from group3 from the local feature-pack;

  5. features from group3 from another-feature-pack.

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 spec of the feature group reference the same parent feature.

For example, suppose we have a parent spec featureP and child spec 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 consists of 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 the parent parameters of the features in the group will implicitly be initialized to the value of the parent parameter of the outer featureP instance.

<config>
  <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:

  1. featureP:parent=p1;

  2. featureP:parent=p2;

  3. featureA:parent=p1,a=a1;

  4. featureA:parent=p2,a=a1;

  5. featureB:parent=p1,b=b1;

  6. featureB:parent=p2,b=b1.

Merging feature groups

There could be a situation when the same feature group is brought into the config as a dependency of other feature groups. Which means its basic feature set is included 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>
  <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

5.2. Configuration model attributes

Configuration models are described in feature-pack.xml file using config elements. feature-pack.xml file may contain zero, one or more config elements. Each configuration may include the following optional attributes:

  • name - the name of the configuration;

  • model - the model name of the configuration.

In XML it could look like this (the content of the config elements has been left out as not important in this example):

<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0">
  <config>
    <!-- anonymous config -->
  </config>

  <config name="config1">
    <!-- named config -->
  </config>

  <config model="model1">
    <!-- model1 model-only config -->
  </config>

  <config model="model1" name="config1">
    <!-- named model1 config -->
  </config>

</feature-pack>

name and model attributes are optional, which means it is well possible to define a configuration w/o those attributes. This kind of configuration is called anonymous. A feature pack may define zero, one or more anonymous configs.

name and model attributes serve as an identity of a config model. They are essential when customizing and merging configuration models.

If a config is associated only with a name (without the model) then only the name will be used as the identity of the config model. If a config is associated with a name and a model then a combination of the name and the model will be used as the identity of the config model.

In the example above config named config1 and config model1:config1 are two unrelated config models.

When a feature-pack is installed, by default all the configs defined in its feature-pack.xml are installed. Users may explicitly specify though which configs should the final installation include and customize those and/or provide their own custom configs.

5.3. Excluding default configs from the installation

To be able to exclude a config, it needs to be identifiable. I.e. it must have a name associated with it. If a config doesn’t have a name it still can be excluded but only altogether with the other configs like this

<installation xmlns="urn:jboss:galleon:provisioning:1.0">
    <feature-pack groupId="org.pm.test" artifactId="fp1" version="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 installation by default. If the attribute is not present, its value is assumed to be true.

NOTE:`feature-pack` element in the example above could as well appear under dependecies element of another feature pack’s feature-pack.xml file. Meaning the XML type of these elements are equivalent - they both describe a customized feature pack. The examples below will display only feature-pack.

If a config is a named config which is not associated with any model then it can be excluded by specifying its name, e.g.

<feature-pack groupId="org.pm.test" artifactId="fp1" version="1.0.0.Final">
    <default-configs>
        <exclude name="config1"/>
    </default-configs>
</feature-pack>

If a config is associated with a name and a model, both of them have to be specified, e.g.

<feature-pack groupId="org.pm.test" artifactId="fp1" version="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"
              groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0">

  <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>

They can be excluded altogether by specifying the model name, e.g.

<installation xmlns="urn:jboss:galleon:provisioning:1.0">
    <feature-pack groupId="org.pm.test" artifactId="fp1" version="1.0.0.Final">
        <default-configs>
            <exclude model="model1"/>
        </default-configs>
    </feature-pack>
</installation>

This installation will include configs model2:config1 and model2:config2.

5.4. Picking default configs into the installation

There are two scenarios when including a config makes sense:

  1. when the config was excluded by <exclude model="model_name"/>;

  2. when inhertance of the default configs was disabled with <default-configs inherit="false">.

The first one of course assumes that the config is associated with both name and model. It could look like this

<feature-pack groupId="org.pm.test" artifactId="fp1" version="1.0.0.Final">
    <default-configs>
        <exclude model="model1"/>
        <include name="config1" model="model1"/>
    </default-configs>
</feature-pack>

The example above excludes all the configs with the model1 except the config1.

Here is an example for the second scenario

<feature-pack groupId="org.pm.test" artifactId="fp1" version="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 configs to be included into the installation.

It is also possible to include the configs of a specific model, e.g.

<feature-pack groupId="org.pm.test" artifactId="fp1" version="1.0.0.Final">
    <default-configs inherit="false">
        <include model="model1"/>
    </default-configs>
</feature-pack>

In this case, all the default configs associated with the model1 will be included into the installation.

5.5. Configuration model merges

Configuration model merges is a way to integrate various products into a single installation. Suppose we want to add new product to an existing installation. Besides adding the actual filesystem content of the product to the existing installation, normally the configuration of the installation will have to be adjusted to include the configuration of the product we are adding to it.

In the provisioning terms, this scenarios can be described as:

  • there is a feature-pack of the main installation (defining its FS content as well as the configuration model);

  • there is the other product’s feature-pack defining its FS content and the default configuration requirements 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:

  1. the product comes with its own standalone config which will not affect the existing installation configuration;

  2. the product’s config will have to be added to the existing installation configuration model;

  3. a combination of the two above (standalone config and a piece of the config that needs to be added to the existing installation configuration).

The first one is simple: we just need to generate two separate configurations: one for each feature-pack.

For the second one, we need to merge the configs from both feature-packs and then generate 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 config 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).

5.5.1. Anonymous configs

Anonymous configs are associated with neither name nor model. E.g.

<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0">
  <config>
    <!-- config body -->
  </config>
</feature-pack>

That means anonymous configs have no identity. They cannot be customized and they are not merged. Each anonymous config is a standalone config.

5.5.2. Named (name-only) configs

The simplest way to provide an identity for the configuration is to give it a name. E.g.

<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0.Final">
  <config 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>
</feature-pack>

Now if another feature-pack provides a config with the same name, e.g.

<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp2" version="1.0.0.Final">
  <config 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>
</feature-pack>

And we include both of these feature packs into the same installation

<installation xmlns="urn:jboss:galleon:provisioning:1.0">
  <feature-pack groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0.Final"/>
  <feature-pack groupId="org.jboss.pm.test" artifactId="fp2" version="1.0.0.Final"/>
</installation>

The provisioned config1 will be the result of merging the config1 from the fp2 into the config1 of from the fp1.

Which config overwrites which 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

org.jboss.pm.test:fp1:1.0.0.Final

feature1

1

fp1

fp1

Feature spec origin Feature spec id

org.jboss.pm.test:fp1:1.0.0.Final

feature2

1

Feature spec origin Feature spec id b

org.jboss.pm.test:fp2:1.0.0.Final

feature1

1

fp2

Feature spec origin Feature spec id

org.jboss.pm.test:fp2:1.0.0.Final

feature3

1

The features of the 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 configs. So this example assumes that both fp1 and fp2 include feature spec feature1.

Here is how fp2 feature-pack.xml had to be written so that feature1 spec could be re-used in fp2 config.

<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp2" version="1.0.0.Final">
  <dependencies>
    <dependency groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0.Final">
      <name>fp1-dep</name>
    </dependency>
  </dependencies>
  <config name="config1">
    <origin name="fp1-dep">
      <feature spec="feature1">
        <param name="id" value="1"/>
        <param name="b" value="fp2"/>
      </feature>
    </origin>
    <feature spec="feature3">
      <param name="id" value="1"/>
    </feature>
  </config>
</feature-pack>

With this feature-pack configuration the resulting config1 will include the following features:

Feature spec origin Feature spec id a b

org.jboss.pm.test:fp1:1.0.0.Final

feature1

1

fp1

fp2

Feature spec origin Feature spec id

org.jboss.pm.test:fp1:1.0.0.Final

feature2

1

Feature spec origin Feature spec id

org.jboss.pm.test:fp2:1.0.0.Final

feature3

1

5.5.3. Named model configs

There are a couple of reasons for adding model attribute into the config identity. One of them is to define the scope for values of name attribute. In this sense, a model could be thought of as a namespace. E.g.

<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0.Final">
  <config 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 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>
<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp2" version="1.0.0.Final">
  <dependencies>
    <dependency groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0.Final">
      <name>fp1-dep</name>
    </dependency>
  </dependencies>
  <config name="main" model="modelA">
    <origin name="fp1-dep">
        <feature spec="feature1">
            <param name="id" value="1"/>
            <param name="b" value="fp2-modelA"/>
        </feature>
    </origin>
  </config>
  <config name="main" model="modelB">
    <origin name="fp1-dep">
      <feature spec="feature1">
        <param name="id" value="1"/>
        <param name="b" value="fp2-modelB"/>
      </feature>
    </origin>
  </config>
</feature-pack>

Installing these two feature-packs (fp2 after the fp1) will result in the following two configurations:

Config model Config name Feature spec origin Feature spec id a b

modelA

main

org.jboss.pm.test:fp1:1.0.0.Final

feature1

1

fp1-modelA

fp2-modelA

Config model Config name Feature spec origin Feature spec id a b

modelB

main

org.jboss.pm.test:fp1:1.0.0.Final

feature1

1

fp1-modelB

fp2-modelB

5.5.4. Model-only configs

Model-only configs are configs associated with a specific model using model attribute of config element but are not associated with any name.

Model-only configs are meant to be merged into other configs. The provisioned installation will contain only anonymous or named configs but not the model-only ones.
Model only configs are merged into all the named configs of the installation that are associated with the same model as the model-only config.
A model-only config will simply be ignored if the installation does not include any named config with the same model as the model-only config.

The idea behind the model-only configs is to be able to define the base for a config of a specific model that every final configuration of that model should include. Model-only configs are always added into the configuration before the named model configs, i.e. the named configs will be added on top of the model-only ones and will overwrite them.

Here is an example:

<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0.Final">
  <config 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 name="main" model="modelB">
    <feature spec="feature1">
      <param name="id" value="1"/>
      <param name="b" value="fp1-modelB"/>
    </feature>
  </config>
</feature-pack>
<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp2" version="1.0.0.Final">
  <dependencies>
    <dependency groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0.Final">
      <name>fp1-dep</name>
    </dependency>
  </dependencies>
  <config name="main" model="modelA">
    <origin name="fp1-dep">
      <feature spec="feature1">
        <param name="id" value="1"/>
        <param name="b" value="fp2-modelA"/>
      </feature>
    </origin>
  </config>
  <config 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 model="modelB">
    <origin name="fp1-dep">
      <feature spec="feature1">
        <param name="id" value="1"/>
        <param name="a" value="fp2-modelB"/>
        <param name="b" value="fp2-modelB"/>
      </feature>
    </origin>
  </config>
  <config 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>
</feature-pack>

Installing these two feature-packs will result in the following configurations:

Config model Config name Feature spec origin Feature spec id a b

modelA

main

org.jboss.pm.test:fp1:1.0.0.Final

feature1

1

fp1-modelA

fp2-modelA

Config model Config name Feature spec origin Feature spec id a b

modelA

test

org.jboss.pm.test:fp1:1.0.0.Final

feature1

1

fp1-modelA

fp1-modelA

modelA

test

org.jboss.pm.test:fp2:1.0.0.Final

feature2

1

fp2-modelA

fp2-modelA

Config model Config name Feature spec origin Feature spec id a b

modelB

main

org.jboss.pm.test:fp1:1.0.0

feature1

1

fp2-modelB

fp1-modelB

Config model Config name Feature spec origin Feature spec id a b

modelB

test

org.jboss.pm.test:fp1:1.0.0.Final

feature1

1

fp2-modelB

fp2-modelB

modelB

test

org.jboss.pm.test:fp2:1.0.0.Final

feature2

1

fp2-modelB

fp2-modelB

Excluding model-only configs with the exclude element

Normally, model-only configs 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 implicitly be ignored by the provisioning mechanism.

Config model designers are encouraged to design configs in a way that model-only configs represent essential configuration and don’t need to be excluded explicitly by the users or should be excluded in exceptional cases.

In a previous chapter it was described how the default configs could be excluded from the provisioned installation by specifying their model name. Here is an example once again

<installation xmlns="urn:jboss:galleon:provisioning:1.0">
    <feature-pack groupId="org.pm.test" artifactId="fp1" version="1.0.0.Final">
        <default-configs>
            <exclude model="model1"/>
        </default-configs>
    </feature-pack>
</installation>

exclude element above does not affect the model-only configs. It affects only the named configs. And in this specific example this fact will not make any difference on the result which is why, a user shouldn’t care about it, since if the named configs are excluded, the model-only configs will automatically be ignored by the provisioning mechanism. Let’s look at an example where it makes a real difference.

<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0.Final">
  <config 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 name="main" model="modelA">
    <feature spec="feature1">
      <param name="id" value="1"/>
      <param name="b" value="fp1-modelB-main"/>
    </feature>
  </config>
</feature-pack>
<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp2" version="1.0.0.Final">
  <dependencies>
    <dependency groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0.Final">
      <name>fp1-dep</name>
    </dependency>
  </dependencies>
  <config name="main" model="modelA">
    <origin name="fp1-dep">
      <feature spec="feature1">
        <param name="id" value="1"/>
        <param name="c" value="fp2-modelA-main"/>
      </feature>
    </origin>
  </config>
</feature-pack>

If we install these feature-packs the resulting config will contain

Feature spec origin Feature spec id a b c

org.jboss.pm.test:fp1: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:1.0"
              groupId="org.jboss.pm.test" artifactId="fp2" version="1.0.0.Final">
  <dependencies>
    <dependency groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0.Final">
      <name>fp1-dep</name>
      <default-configs>
        <exclude model="modelA"/>
      </default-configs>
    </dependency>
  </dependencies>
  <config name="main" model="modelA">
    <origin name="fp1-dep">
      <feature spec="feature1">
        <param name="id" value="1"/>
        <param name="c" value="fp2-modelA-main"/>
      </feature>
    </origin>
  </config>
</feature-pack>

If we install fp2, the provisioned configuration will contain

Feature spec origin Feature spec id a b c

org.jboss.pm.test:fp1:1.0.0.Final

feature1

1

fp1-modelA

fp1-modelA

fp2-modelA-main

The model-only config from fp1 is still effective because it is considered being essential for any named config of modelA. In case it still has to be excluded from the provisioned config you can add named-only-models="false" attribute to exclude element, e.g.

<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp2" version="1.0.0.Final">
  <dependencies>
    <dependency groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0.Final">
      <name>fp1-dep</name>
      <default-configs>
        <exclude model="modelA" named-only-models="false"/>
      </default-configs>
    </dependency>
  </dependencies>
  <config name="main" model="modelA">
    <origin name="fp1-dep">
      <feature spec="feature1">
        <param name="id" value="1"/>
        <param name="c" value="fp2-modelA-main"/>
      </feature>
    </origin>
  </config>
</feature-pack>

exclude element above affects both named and model-only configs 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 the model-only configs

In an earlier chapter it was shown how the default configs of a feature-pack could be suppressed. Let’s now include a model-only config in the example.

<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0.Final">
  <config 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 name="main" model="modelA">
    <feature spec="feature1">
      <param name="id" value="1"/>
      <param name="b" value="fp1-modelB-main"/>
    </feature>
  </config>
</feature-pack>
<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp2" version="1.0.0.Final">
  <dependencies>
    <dependency groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0.Final">
      <name>fp1-dep</name>
      <default-configs inherit="false"/>
    </dependency>
  </dependencies>
  <config name="main" model="modelA">
    <origin name="fp1-dep">
      <feature spec="feature1">
        <param name="id" value="1"/>
        <param name="c" value="fp2-modelA-main"/>
      </feature>
    </origin>
  </config>
</feature-pack>

With inherit="false" attribute of default-configs element we indicated that the default configs of fp1 should not be included into the provisioned installation of fp2. But it does not affect the model-only configs. So the model-only modelA config 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 anonymous, named and model-only configs:

<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp2" version="1.0.0.Final">
  <dependencies>
    <dependency groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0.Final">
      <name>fp1-dep</name>
      <default-configs inherit="false" inherit-unnamed-models="false"/>
    </dependency>
  </dependencies>
  <config name="main" model="modelA">
    <origin name="fp1-dep">
      <feature spec="feature1">
        <param name="id" value="1"/>
        <param name="c" value="fp2-modelA-main"/>
      </feature>
    </origin>
  </config>
</feature-pack>

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

5.6. Content of config element

config element is basically an extended version of feature-group element. Meaning that everything that is allowed in the body of feature-group is allowed in config element. Which means feature and feature-group elements (as well as origin element for explicit dependency origins).

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 or as a child of installation element, it represents all the configs with the matching identity merged into one model from all the feature-pack dependencies up to the current point.

E.g. if feature-pack FP1 depends on feature-pack FP2 which includes config model M1 named N1. Element config with attributes model="M1" name="N1" added to FP1 will represent the corresponding config from FP2 (unless the config inheritance was explicitly disabled in FP1), i.e. the content of config 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.

5.6.1. Config properties

props element allows to attach various properties to the configuration described by the config element that can be meaningful for the provisioning plugin processing the configuration. E.g.

<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp1" version="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>

5.6.2. Overwriting properties during config inclusion

When a default config is included, its properties can be overwritten, e.g.

<installation xmlns="urn:jboss:galleon:provisioning:1.0">
    <feature-pack groupId="org.pm.test" artifactId="fp1" version="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 config will include the following properties:

  • save-to-file=main-model-a.xml;

  • other=thing.

5.6.3. Overwriting properties when merging configs

When the configs are merged, their properties are also merged. The config that is included later into the installation overwrites the properties of the config which was added before. E.g.

<feature-pack xmlns="urn:jboss:galleon:feature-pack:1.0"
              groupId="org.jboss.pm.test" artifactId="fp1" version="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:1.0"
              groupId="org.jboss.pm.test" artifactId="fp2" version="1.0.0.Final">
  <dependencies>
    <dependency groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0.Final">
      <name>fp1-dep</name>
    </dependency>
  </dependencies>
  <config name="main" model="modelA">
    <props>
      <prop name="save-to-file" value="main-model-a.xml"/>
    </props>
    <origin name="fp1-dep">
      <feature spec="feature1">
        <param name="id" value="1"/>
        <param name="a" value="fp2-modelA"/>
      </feature>
    </origin>
  </config>
</feature-pack>

The resolve configuration modelA:main will contain the following properties:

  • save-to-file=main-model-a.xml;

  • other=thing.

5.7. Configuration package dependencies

config elements may include feature-pack package dependencies. So that when a config is included into the installation, the relevant packages 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:1.0"
              groupId="org.jboss.pm.test" artifactId="fp1" version="1.0.0.Final">
  <config model="modelA">
    <packages>
     <package name="p1"/>
     <package name="p2" optional="true"/>
    </packages>
  </config>
</feature-pack>

Now every config of the modelA will depend on and bring into the installation the specified packages.

5.8. 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 configs as a list. Certain configuration models though may depend on other configuration models being generated first. To eliminate the trouble of ordering the configs according to their dependencies, config 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 configs of model host will appear in the resolved config list after all the domain model configs. config-dep id is used to identify the config dependencies when the config models are merged.

The example above illustrates only model dependencies. But config-dep may also include name attribute.

5.9. Arranging features in configs

Resolved configuration models are meant to be further processed by provisioning plugins that actually generate the final configuration files. A resolved config is basically is a collection of features and properties. Plugins simply iterate through the features in a resolved config and generate the corresponding configuration fragments.

The order in which features appear in the resolved config may be significant. By default the order of the features in the resolved config reflects the order in which the features where added to the config, i.e. the order in which the features appear in config element. Although, in case there 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 config model before F2, in the resolved config F2 will appear before F1.

5.9.1. Feature branches

In the resolved config features are actually organized into branches. In the simplest case, there is only one branch in the config and all the features of the config appear on that branch.

There are cases though, when a set of features has to be handled in a different way than the rest of the features from the same config. E.g. there could be a few features that form a circular dependency. The mechanism may automatically identify those and notifies the plugins in case they need to handle them in a special way. Other examples of branches will be described below.

5.9.2. Batches

Batch is nothing more than a flag in a branch. This flag is meant to indicate to the plugins whether features on the branch should be handled in a batch (i.e. in a transactional way) or not. In other words, if batch is on for a branch it means "transaction required" for this branch. This is useful for cases when features form circular dependencies and handling them one by one may result in referential (or other) integrity constraint violation in the final config generation.

By default, branches are not flagged as batches. This can be configured though with config property config.branch-is-batch. E.g.

    <config model="standalone">
        <props>
            <prop name="config.branch-is-batch" value="true"/>
        </props>
        <!-- the rest is skipped -->

This means that in all the standalone configs all the branches will be flagged as batches by default.

Batch flag can further be enabled or disabled for a specific branch by using 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 flags branch core-service.management as batch.

5.9.3. Branch per feature spec

In some cases it might be useful to arrange features in the resolved config by their specs. Which means a plugin prefers to handle all the features of Spec1 first then all the features of Spec2, etc. The mechanism can be instructed to 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 will be ordered according to feature dependencies. E.g. if features of Spec1 reference features of Spec2, the branch of features Spec2 will appear in the config before the branch of Spec1.

The example above is arranging all the features in the config 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 -->

5.9.4. Isolating circular dependencies

The mechanism may identify circular dependencies between features in a config model 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 -->

5.9.5. Parent-children branch

Often in configs features form parent-children references. It could be useful for plugins to arrange features by 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 which contain all the features that are children (direct or transitive) of the parent feature SpecP.

5.9.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.

5.9.7. Merging independent branches

After the config has been resolved it the could be branches have certain common characteristics. E.g. most probably some features in the config will depend other features. Which means that some feature branches will 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). Those independent branches could be merged into one independent branch. If that is useful it can 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 -->

5.9.8. Merging branches with the same dependencies

While the previous option merges only the independent branches, this one identifies branches with identical dependencies on other branches and merges them into one 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 -->

6. 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>2.0.0.Alpha6-SNAPSHOT</version>
</dependency>
Table 2. Goals

install-feature-pack

Installs a feature-pack into an empty directory or into an existing installation

provision

Provisions an installation that consists of one or more feature-packs at a specified location

6.1. install-feature-pack

6.1.1. galleon:install-feature-pack

Full name: org.jboss.galleon:galleon-maven-plugin:2.0.0.Alpha6-SNAPSHOT:install-feature-pack

6.1.2. Description

This maven plugin installs a feature-pack into an empty directory or a directory that already contains an installation, in which case the product the feature-pack represents will be integrated into an existing installation.

6.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.

Table 3. Required Parameters

Name

Type

Since

Description

[installDir]

File

-

The target installation directory.
Alias is: install-dir.

Table 4. Optional Parameters

Name

Type

Since

Description

[customConfig]

File

-

Path to a file containing config that should be installed.
Alias is: custom-config.

[excludedPackages]

List

-

Explicitly excluded packages from the installation.
Alias is: excluded-packages.

[featurePack]

ArtifactItem

-

Legacy Galleon 1.x feature-pack artifact coordinates as (groupId - artifactId - version) if not specified the feature-pack must be a transitive dependency of a feature-pack with the version specified. NOTE: either this parameter or 'location' must be configured.
Alias is: feature-pack.

[includedConfigs]

List

-

Default feature-pack configs that should be included.
Alias is: included-configs.

[includedPackages]

List

-

Explicitly included packages to install.
Alias is: included-packages.

[inheritConfigs]

boolean

-

Whether to inherit the default feature-pack configs.
Default value is: true.
Alias is: inherit-configs.

[inheritPackages]

boolean

-

Whether to install the default package set.
Default value is: true.
Alias is: inherit-packages.

[location]

String

-

Galleon2 feature-pack location NOTE: either this parameter or 'feature-pack' must be configured.

[pluginOptions]

Map

-

Arbitrary plugin options recognized by the plugins attached to the feature-pack being installed.
Alias is: plugin-options.

6.1.4. Parameter Details

customConfig
Path to a file containing config that should be installed.

  • Type: java.io.File

  • Required: No

  • Alias: custom-config

excludedPackages
Explicitly excluded packages from the installation.

  • Type: java.util.List

  • Required: No

  • Alias: excluded-packages

featurePack
Legacy Galleon 1.x feature-pack artifact coordinates as (groupId - artifactId - version) if not specified the feature-pack must be a transitive dependency of a feature-pack with the version specified. NOTE: either this parameter or 'location' must be configured.

  • Type: org.jboss.galleon.maven.plugin.util.ArtifactItem

  • Required: No

  • Alias: feature-pack

includedConfigs
Default feature-pack configs that should be included.

  • Type: java.util.List

  • Required: No

  • Alias: included-configs

includedPackages
Explicitly included packages to install.

  • Type: java.util.List

  • Required: No

  • Alias: included-packages

inheritConfigs
Whether to inherit the default feature-pack configs.

  • Type: boolean

  • Required: No

  • Default: true

  • Alias: inherit-configs

inheritPackages
Whether to install the default package set.

  • Type: boolean

  • Required: No

  • Default: true

  • Alias: inherit-packages

installDir
The target installation directory.

  • Type: java.io.File

  • Required: Yes

  • Alias: install-dir

location
Galleon2 feature-pack location NOTE: either this parameter or 'feature-pack' must be configured.

  • Type: java.lang.String

  • Required: No

pluginOptions
Arbitrary plugin options recognized by the plugins attached to the feature-pack being installed.

  • Type: java.util.Map

  • Required: No

  • Alias: plugin-options

6.2. provision

6.2.1. galleon:provision

Full name: org.jboss.galleon:galleon-maven-plugin:2.0.0.Alpha6-SNAPSHOT:provision

6.2.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>

6.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.

Table 5. Required Parameters

Name

Type

Since

Description

[featurePacks]

List

-

A list of feature-pack configurations to install.
Alias is: feature-packs.

[installDir]

File

-

The target installation directory.
Alias is: install-dir.

Table 6. Optional Parameters

Name

Type

Since

Description

[customConfig]

File

-

Path to a file containing config that should be installed.
Alias is: custom-config.

[offline]

boolean

-

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.
Default value is: true.
Alias is: offline.

[pluginOptions]

Map

-

Arbitrary plugin options.
Alias is: plugin-options.

[resolveLocals]

List

-

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.
Alias is: resolve-locals.

6.2.4. Parameter Details

customConfig
Path to a file containing config that should be installed.

  • Type: java.io.File

  • Required: No

  • Alias: custom-config

featurePacks
A list of feature-pack configurations to install.

  • Type: java.util.List

  • Required: Yes

  • Alias: feature-packs

installDir
The target installation directory.

  • Type: java.io.File

  • Required: Yes

  • Alias: install-dir

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: true

  • Alias: offline

pluginOptions
Arbitrary plugin options.

  • Type: java.util.Map

  • Required: No

  • Alias: plugin-options

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

Table 7. Feature-pack parameters

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>

7. 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, upgrade.

7.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/upgrade/…​ 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.

7.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 upgrade) only require the product part (<product>[@universe]) of an FPL. For example:

state upgrade --products=wildfly

7.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 info wildfly:current#1.0.0-Alpha1

7.4. 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: To retrieve the set of feature-pack specific options call:
feature-pack info <[FPL|FPID] | [--file=<path to fp zip file>]> --type=options
You can then use the listed options (if any) to customize your installation.

7.5. Un-installing a feature-pack

uninstall [FPID] [--dir=<installation dir>]

This will remove the content installed by the feature-pack identified by the FPID.

7.6. Patching an installation

Use the install command to patch an existing installation.

install [--file=<path to patch fp zip file>]> [--dir=<installation dir>] [--verbose] [feature-pack specific options]

7.7. Checking for updates

state check-updates [--dir=<installation dir>] [--include-all-dependencies] [--products=<list of products>]

If no directory is provided, the current directory is used. If no products are provided, all installed products are checked for updates.

7.8. Upgrading an installation

state upgrade [--dir=<installation dir> [--include-all-dependencies] [--yes] [--products=<list of products>] [list of discovered feature-pack options]

Display the ist of available updates/patches then upgrade. If no directory is provided, the current directory is used. If --yes is provided, the command will proceed without asking for confirmation.

7.9. Observing an installation

[my-dir]$ state info [--dir=installation] --type=[configs|dependencies|patches]

Display the set of dependencies and/or configurations and/or applied patches. All is displayed by default.

7.10. Observing a feature-pack

[my-dir]$ feature-pack info <[FPL|FPID] | [--file=<path to fp zip file>]> --type=[configs|dependencies|options]

Display the set of dependencies and/or configurations and/or options usable when installing/provisioning/upgrading. All is displayed by default.

7.11. Exporting an installation to xml

[my-dir]$ state export <new generated xml file> --dir=<installation>

7.12. Provisioning an installation from xml

[my-dir]$ state provision <xml file> --dir=<target installation directory>

7.13. Exploring an installation or a feature-pack.

To explore an installation:
[my-dir]$ state explore --dir=installation

To explore a feature-pack:
[my-dir]$ feature-pack explore <[FPL|FPID] | [--file=<path to fp zip file>]

Once exploring, prompt, ls, cd and pwd commands are bound to the feature-pack (or installation) exposed file-system.

[/]$ ls
configs
feature-specs
packages
[/]$ state leave
[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.
The set of available commands is limited when in “navigation mode”. Only “cd, ls, pwd and state info|leave” are available. Use state leave to exit this mode.

Use ‘ls’ to visualize any item. Use ‘cd’ to navigate to a given node.

7.14. Searching the current state

When exploring, editing or composing a new state, one can search the packages and features.

[/]$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.

7.15. 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 | path to provisioning XML file>
[/]$ <TAB>
cd feature-pack ls pwd state
[/]$ ls
configs
dependencies
feature-specs
packages

The filesystem is similar to explore, with the addition of dependencies that contains full content of all added feature-packs.

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. Use state leave to exit the composition mode.

NB: The set of exposed commands by completer is dynamic and is adjusted according to the current state.

7.16. Managing universes

A universe can be added/removed to/from an existing installation or to a new/edited state.
NB: In order to add/remove a universe to/from an installation you must first cd in the directory of the installation.

Add a named or default (without using the --name option) universe to the current provisioning state or installation.
[/]$ universe add [--name=<universe name>] --factory=<universe factory> --location=<universe location>

Remove a named or default (without using the --name option) universe from the current provisioning state or installation.
[/]$ universe remove [--name=<universe name>]

7.17. Listing products of universes

[/]$ universe list

This command lists all the products and available builds present in all the installed universes.

You can search for products that match a given pattern using --product=<pattern>.
For example:
[/]$ universe list --product=wildfly*

7.18. Exporting or provisioning the current state

At any time, one can export the provisioning XML file or directly provision from the current state:

[/]$ state export <path to generated xml file> | state provision <dir of new installation>

Use state export to validate that what you get in the XML is in sync with the expose state. In case you find something wrong, shout to me ;-)!
Exporting a state without any XML target file will display the XML content in the CLI console.
The command state info can be used to get high level information.

7.19. Adding a feature-pack

[/]$ fp add <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.

NB: A runtime based on the added full feature-pack is built in order to retrieve dependencies content and some completion content. This structure is cached for re-use.

7.20. Removing a feature-pack

[/]$ fp remove <FPL|FPID>

7.21. Including a default configuration

[/]$ config include <model>/<name> [--origin=<fp origin>]

Origin is optional, by default will be included from all fp that expose it.

7.22. Removing an included default configuration

[/]$ config remove-included <model>/<name> [--origin=<fp origin>]

The completer only proposes the set of configurations that have been previously included. Same for fp. Origin is optional, by default will be remove from all fp that include it.

7.23. Excluding a default configuration

[/]$ config exclude <model>/<name> [--origin=<fp origin>]

Origin is optional, by default will be excluded from all fp that expose it.

7.24. Removing an excluded default configuration

[/]$ config remove-excluded <model>/<name> [--origin=<fp origin>]

The completer only proposes the set of configurations that have been previously excluded. Same for fp. Origin is optional, by default will be remove from all fp that exclude it.

7.25. Reseting a configuration

[/]$ config reset <model>/<name>

The custom content of this configuration is removed.

NB: This has no effect on included/excluded configurations.

7.26. Including a default package

[/]$ packages include <fp origin>/<package name>

7.27. Removing an included default package

[/]$ packages remove-included <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 fp that exclude it.

7.28. Excluding a default package

[/]$ packages exclude <fp origin>/<package name>

7.29. Removing an excluded default package

[/]$ packages remove-excluded <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 fp that exclude it.

7.30. Adding a new feature

[/]$ feature add <config model/name> <path to feature-spec> <dynamic set of feature param=<value>>

For example:
feature add 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.

7.31. Removing a feature

[/]$ feature remove <full path to feature inside a configuration>

For example:
feature remove standalone/standalone.xml/interface/toto

8. 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.

8.1. Relying on maven settings

In order to makes the cli to use a maven settings file call: mvn set-settings-file <path to settings xml file> In order to remove the reference to the settings file call: mvn set-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.

8.2. Adding new remote repositories

Type the following commands:
mvn add-repository --name=myrepo --url=http://foorepo

8.3. Repository policies (this could be made configurable)

Never update of local artifacts.
Warn if checksum differs.

8.4. Advanced maven configuration

Proxy, authentication, mirroring and offline are only supported when setting a maven xml settings file.

8.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: mvn set-local-repository <path to your local repository directory>
In order to reset to the default local maven repository call: mvn set-local-repository

8.6. Display maven configuration

Call command: mvn info

8.7. 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.

8.8. Fetching 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: mvn fetch-feature-pack <stream name> [--verbose]

8.9. 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.