Fabric8 Documentation

Profiles

A profile is a description of how a logical group of containers needs to be provisioned. It contains a list of:

  • System properties
  • OSGi Configuration Admin PIDs
  • Maven artifact repositories
  • Bundles
  • Karaf feature repositories
  • Features

and also defines the OSGi framework that is going to be used.

Each profile can have none, one or more parents, and this allows you to have profile hierarchies and a container can be assigned to one or more profiles. Profiles are also versioned, which allows you to keep different versions of each profile and then upgrade or rollback containers by changing the version of the profiles they use.

Each profile may also define none, one or more dependents. This allows a profile to specify any containers that must be active for it to start, an example would be requiring that a MongoDB container is active so that a profile can use it as a database.

Profile hierarchies

It is quite often that multiple profiles share similar bits of configuration. Its quite common for different applications to use common frameworks libraries etc. Defining everything from group up for each profile can be a real pain and is not that easy to maintain. To avoid having duplicate configuration across profiles and reduce the required maintenance, Fabric uses a hierarchical model for profiles, which allows you to build a generic profile which contains common configuration and then inherit the common bits.

The section below describes the profiles that are shipped with Fabric out of the box and are a good example of how profile hierarchies work.

Out of the box profiles

Fabric provides a rich set of profiles *"out of the box" that can be used as the basic building blocks for definining your own profiles. The most important profiles are:

  • default The default profile defines all the basic stuff that fabric needs to run. For example it defines the fabric-agent feature, the fabric registry url & the list of maven repositories that can be used to download artifacts from.
  • karaf It is a child of default (so it doesn't need to define the same things again. It also defines the karaf feature repositories, that can be used for defining any karaf feature.
  • camel It is a child of karaf. It also defines the camel feature repositories and some core camel features such as camel-core & camel-blueprint. Any profile for describing camel application is suggested to inherit this one.
  • cxf It is a child of karaf. It also defines the cxf feature repositories and some core cxf features. It is intended to be the parent of any profile that describes a cxf application.
  • mq-base A profile that inherit the karaf profile and defines the mq-fabric feature
  • mq It is a child of the mq-base profile and it also provides a fuse mq broker configuration.
  • esb It is a child of camel,mq & more profiles and also defines the Fuse ESB feature repository.

Profile dependencies

A profile defines a dependency within a io.fabric8.profile.dependency-[name].properties file, where [name] can be any descriptive name for a particular dependency.

This is an example dependency defining that a container must exist with the MongoDB profile:

kind = ZOOKEEPER_SERVICE
zookeeperPath = /fabric/registry/clusters/mongodb/default
summary = You must have a MongoDB instance running to be able to start this profile.
profileWildcards = mongodb

kind only supports ZOOKEEPER_SERVICE as a method of determining whether a dependency is present. zookeeperPath defines the path in the registry whose child nodes will be containers of the appropriate profile(s) for this dependency. profileWildcards defines what profile ids to match on. If an id within profileWildcards is not contained within part of a profile id of the container, then no match is made. summary specifies a message to be displayed in hawt.io when no dependent container is found.

Dependencies will attempt to match by profileWildcards first, and if no dependent container is found, it will then use profileTags. For a match to be made by profileTags, all the tags specified must be present on the profile of the dependent container. A match is still made if the dependent container has more tags than was defined in profileTags.

Changing the profile of a container

At any given time you are able to change one of more of the profiles that are assigned to a container. You can use the fabric:container-change-profile command as shown below:

  fabric:container-change-profile mycontainer myprofile

The command above will assign the myprofile profile to mycontainer. All profiles previously assigned to the container will be removed. You can also specify multiple profiles to the container:

   fabric:container-change-profile mycontainer myprofile myotherprofile

Creating and editing profiles

To see the list of available profiles you can use the fabric:profile-list:

    fabric:profile-list

The command will display all the profiles and also display their parents and the number of containers that currently make use of each profile:

    [id]                                     [# containers] [parents]
    activemq-client                          0              default
    aws-ec2                                  0              cloud
    camel                                    0              karaf
    camel-jms                                0              camel, activemq-client
    cloud                                    0              karaf
    cloudservers-uk                          0              cloud
    cloudservers-us                          0              cloud
    cxf                                      0              karaf
    default                                  0
    dosgi                                    0              karaf
    example-camel                            0              karaf
    example-cxf                              0              cxf
    example-mq                               0              example-mq-base
    example-mq-base                          0              karaf
    example-mq-cluster                       0              example-mq-base
    fabric                                   1              karaf
    fmc                                      0              default
    hadoop                                   0              karaf
    hadoop-datanode                          0              hadoop
    hadoop-namenode                          0              hadoop
    hawtio                                   0              default
    insight                                  0              default
    insight-hdfs                             0              insight
    karaf                                    0              default
    mq                                       0              mq-base
    mq-base                                  0              karaf
    nmr                                      0              karaf

To see exactly what a profile defines you can use the fabric:profile-display command. For example let's take a look of what is defined in the camel profile.

    fabric:profile-display camel

This command will display all information available for the camel profile:

    Profile id: camel
    Version   : 1.0
    Parents   : karaf
    Associated Containers :

    Container settings
    ----------------------------
    Repositories :
        mvn:org.apache.camel.karaf/apache-camel/2.13.0/xml/features

    Features :
        camel-blueprint/2.13.0
        fabric-camel/1.1.0
        camel-core/2.13.0

Of course this command does not display what is inherited from the parents of the profile (in this example the karaf profile). To unfold the profile hierarchy and also see the inherited configuration you can use the --overlay option:

    fabric:profile-display --overlay camel

Creating a new profile

In order to create a new profile that will describe how your application should be provisioned, you can use the fabric:profile-create command.

    fabric:profile-create myprofile

To specify one ore more parents to the profile you can use the --parents option:

    fabric:profile-create --parents camel myprofile

As soon as the profile is created you can modify the profile, using the commands that are described in the following sections of the document.

Adding or removing a feature to a profile

In order to edit one of the existing profile you can use the fabric:profile-edit command.

In this example I will use the command to add the camel-jclouds feature to the camel profile.

    fabric:profile-edit --features camel-jclouds camel

After the command I can display again the profile and see how the camel profile looks like now. You should now be able to see the camel-jclouds feature in the list of features of the camel profile.

    Features :
        camel-jclouds
        camel-blueprint/2.13.0
        camel-core/2.13.0
        fabric-camel/1.1.0

If you want to remove a feature from the profile you can make use of the --delete option. So, if gor example you need to remove the camel-jclouds feature:

    fabric:profile-edit --delete --features camel-jclouds camel

Modifying a configuration pid in a profile

A more complex example is when you need to modify the a configuration pid of a profile. A configuration pid is actually a list of key value pairs. So to edit or add a new key value pair to a specific pid you can use the -pid and specify the pid and key value in the following format pid/key=value. In the following example, I will modify the io.fabric8.agent pid and change the maven repository list. The default profile should contain a section like this:

    Agent Properties :
          org.ops4j.pax.url.mvn.repositories= \
            http://repo1.maven.org/maven2@id=central, \
            https://repo.fusesource.com/nexus/content/groups/public@id=fusepublic, \
            https://repository.jboss.org/nexus/content/repositories/public@id=jbosspublic, \
            https://repo.fusesource.com/nexus/content/repositories/releases@id=jbossreleases, \
            https://repo.fusesource.com/nexus/content/groups/ea@id=jbossearlyaccess, \
            http://repository.springsource.com/maven/bundles/release@id=ebrreleases, \
            http://repository.springsource.com/maven/bundles/external@id=ebrexternal, \
            https://oss.sonatype.org/content/groups/scala-tools@id=scala

Let's see how we can change the Agent Properties section (the agent properties is represented by the io.fabric8.agent pid that was mentioned above):

             fabric:profile-edit --pid io.fabric8.agent/org.ops4j.pax.url.mvn.repositories=http://repositorymanager.mylocalnetwork.net default

Now the fabric:profile-edit command for the default profile should be similar to:

             Agent Properties :
                   org.ops4j.pax.url.mvn.repositories = http://repositorymanager.mylocalnetwork.net

Profile Editor

The profile edit command is quite flexible, however in some cases, you would really prefer a more traditional way of editing. Mainly becasue:

  • You want to perform many changes at once
  • It feels more natural

This is why fabric provides a profile editor embedded to your shell. You can use it, like:

  fabric:profile-edit default (with no options)

Opening the profile inside the editor

The editor supports the basic editor functionality like undo, redo, forward/backward search, highlighting etc. What you are actually editing is the content of the io.fabric8.agent pid. But you can use it to also edit any other pid or resource in your profile. For example to edit the io.fabric8.maven pid of the fabric profile, you can simply:

  fabric:profile-edit --pid io.fabric8.maven fabric

Editing a pid

A pretty similar approach applies to any resouce under the profile. For example, to edit the broker.xml of the mq-base profile:

  fabric:profile-edit --resource broker.xml mq-base

Editing a pid

Profile versions

Every profile has at least one version. When assigning a profile to a container, you actually assign both the profile and the version. The fabric-agent, will choose the defined version and retrieve all the information provided by the specific version of the profile.

Any change to a profile, will take immediate effect. This means that if there are containers that are assigned the version of a profile that was just modify will pick up the change immediately. So it is recommended, to create a new version of a profile whenever you need to make changes and then assign the new version to the container. This allows you to complete your changes, test them and rollback to the previous version if you encounter issues.

Create a new version

You are able to create a new version using the fabric:version-create. The default version is 1.0 so let's create 1.1.

    fabric:version-create 1.1

Once the version has been created an instance of each profile has been created for the new version. To be more precise a copy of the latest version of each profile has been added to the new version. Now you can display or modify the 1.1 version of each profile. Let's display the camel profile:

    fabric:profile-display --version 1.1 camel

The output will be identical to the 1.0 version of the profile, since we haven't applied any change to the profile yet.

But how do we modify a specific version of profile?

All you need to do is to specify the version right after the profile argument. For example let's add the camel-jclouds component to version 1.1 of the camel profile:

    fabric:profile-edit --features camel-jclouds camel 1.1

Please note, that this will not affect any of your existing container, not until you upgrade them to the 1.1 version.

Rolling upgrades & rollbacks

Fabric provides commands for upgrading (increasing the version) and rolling back (decreasing the version) of the profiles assigned to a container. In order to upgrade a single container to the 1.1 version that we created in the previous section you can use the fabric:container-upgrade. For example:

    fabric:container-upgrade 1.1 mycontainer

The command above will make make mycontainer to use the version 1.1 of all the profiles that have been currently assigned to it.

If for any reason you wish to rollback to the previous version, you can make use of the fabric:container-rollback command.

    fabric:container-rollback 1.1 mycontainer

That doesn't look like rolling, does it. You are strongly recommended to test your changes on a single container, before applying the changes to the whole cluster. Applying an upgrade to all containers can be achieved using the --all option as demonstrated below.

      fabric:container-upgrade --all 1.1 mycontainer

Complete walk through

The following clip demonstrates most of the profile concepts & features described so far. It uses a small Fabric cluster of 5 containers on EC2, plus 1 Fabric registry. It describe how to modify profiles and explains how to perform single and rolling container upgrades.

Importing and exporting profiles

There are cases where you have put quite a lot of effort in creating the profiles that much your needs and you want to store them somewhere. A good example is when you move from the development environment to the staging or the production environment. You simply just don't want to go over the process of creating the profiles again. For such cases Fabric allows you export your profiles in text and also import them back. So you can safely store them or even import them to a version control system.

To export the Fabric profiles you can use the fabric:export

     fabric:profile-export

This command will export all the profiles to files. The default export location is the fabric/export folder under the karaf home directory. To change the default location you just need to specify the path as an argument:

     fabric:profile-export /path/to/my/export/location

In a similar way the import operation works. Please keep in mind that by default when creating a Fabric the fabric:create command will import everything it finds in fabric/import under the karaf home folder.

    fabric:create

to specify an other folder for importing to the registry you can simply use the --import-dir option. For example:

    fabric:create --import-dir /path/to/my/import/location

Of course there are cases where you need to import profiles after fabric has been created. You can use the the fabric:export as described below:

    fabric:profile-import /path/to/my/profiles.zip

The profile-import command import profiles stored as zip files from url locations. You can also import using maven coordinates such as:

    fabric:profile-import mvn:com.foo/mystuff/1.0/zip/profile

Fabric provides a Maven Plugin fabric8:zip which allows to export profiles to zips. Read more about this at the Continues Deployment section.

Fabric provides the maven fabric8 plugin supporting the fabric8:zip goal to export profiles to zips. This allows end users to develop projects, and easily export their projects as zips which can be imported into fabric. Read more about this at the continues deployment section.

Importing initial profiles

When fabric is started it imports an initial set of profiles from the <fabric_home>/fabric/import directory.

In addition fabric imports additional .zip files from the following two sources:

  1. .zip files which have been copied to the <fabric_home>/fabric directory.
  2. .properties file which haven been copied to the <fabric_home>/fabric directory.

In the .properties files, you specify url locations for .zip files to be imported. For example fabric uses this to import additional profiles such as the quickstarts, by having a io.fabric8.import.profiles.properties file with the following content

importProfileURLs = ${env:FABRIC8_IMPORT_PROFILE_URLS?:mvn:io.fabric8.quickstarts/fabric8-quickstarts-parent/${version:fabric}/zip/profile}

The url above is using the environment property resolver to either load urls from the given environment variable, or if not provided, then use the default value which is mvn:io.fabric8.quickstarts/fabric8-quickstarts-parent/${version:fabric}/zip/profile. Notice how the url uses the ?: elvis operator so we can lookup the environment variable, and if not given, then fallback and use the default value. The value ${version:fabric} will get replaced with the version of fabric8.

The environment variable FABRIC8_IMPORT_PROFILE_URLS can be used to define custom profiles to be loaded instead of the quickstarts. Multiple urls can be separated bt comma. For example to load two custom profiles instead of the quickstarts, then the environment can be configured with:

export FABRIC8_IMPORT_PROFILE_URLS="mvn:com.foo/myprofiles/1.0,mvn:com.foo/myotherprofiles/1.0"
Disabling quickstarts

This allows easily to disable importing the quickstarts, by either deleting the io.fabric8.import.profiles.properties file, or disable the above line, by prefixing the line with the # character, or setting the environment variable FABRIC8_IMPORT_PROFILE_URLS to the value false.