1.2. Flavors

The same version of a package or group can be built simultaneously for multiple deployment conditions, such as for a 64-bit architecture or deployment as part of a VMware virtual machine. Each condition is called a flavor specification, and all possible conditions together make up a flavor of that package or group.

rBuilder controls flavors for you automatically. When you create image definitions for your appliance in rBuilder, each definition groups together the appropriate flavor specifications to represent each image definition. Then, rBuilder builds each package and group for all the flavors, thus covering all the image definitions.

There are only three reasons you'd need to concern yourself with flavors outside of this automated process:

When querying information about a component, package, or group, its associated flavor is a string of values separated by commas in square brackets. Use the --flavors option to reveal the flavor that aligns with the flavor specs of your current Conary-based system, and use --all-flavors to show all flavors in a repository:

$> conary q group-core --flavors
group-core=2.1.1-0.133-2[~!dom0,~!domU,~!vmware,~!xen is: x86(i486,i586,i686,sse,sse2) x86_64]

$> conary rq group-dist=conary.rpath.com@rpl:2 --flavors
group-core=2.0.1-0.3-1[~!dom0,~!domU,~!vmware,~!xen is: x86(i486,i586,i686,sse,sse2) x86_64]

$> conary rq group-dist=conary.rpath.com@rpl:2 --all-flavorsgroup-dist=2.0.1-0.3-1[dom0,~!domU,~!vmware,xen]
group-dist=2.0.1-0.3-1[~!dom0,domU,~!vmware,xen]
group-dist=2.0.1-0.3-1[~!dom0,~!domU,vmware,~!xen]
group-dist=2.0.1-0.3-1[~!dom0,~!domU,~!vmware,~!xen]
group-dist=2.0.1-0.3-1[dom0,~!domU,~!vmware,xen is: x86 x86_64]
group-dist=2.0.1-0.3-1[~!dom0,domU,~!vmware,xen is: x86 x86_64]
group-dist=2.0.1-0.3-1[~!dom0,~!domU,vmware,~!xen is: x86 x86_64]
group-dist=2.0.1-0.3-1[~!dom0,~!domU,~!vmware,~!xen is: x86 x86_64]

The most recent versions of Conary shorten these flavors to show only the specifications that are relevant.

When reading a flavor, note the following mnemonics for each flavor specification, using the example "vmware" which refers to conditions that prepare the software to be part of a VMware virtual machine:

Table 1.1. Mnemonics for reading flavor specifications

MnemonicExampleHow it reads
(no preceding mark)vmwarevmware -- must be built for VMware; if this condition cannot be met, let the build fail
~~vmwareprefers vmware -- preferred built for VMware; if this condition cannot be met, don't let that stop building
!!vmwarenot vmware -- must not be built for VMware; if this condition cannot be met, let the build fail
~!~!vmwareprefers not vmware -- preferred not built for VMware; if this condition cannot be met, don't let that stop building

1.2.1. Add Flavor Specifications to your Product Definition

To see all the flavor specifications built into a platform, beyond the automatically-abbreviated list of relevant flavor specs, you need to locate the recipe used to build the platform. Browse the repository to find the groups in the platform and to read the group recipes. For example, group-dist:source is used to build rPath Linux 2 on conary.rpath.com@rpl:2. In the recipe code, find the "if," "elif," and "else" lines that define these flags (generally following the consistent pattern for recipes in the Conary API).

FIXME: Example here? More to come in future drafts.

The abbreviated list usually includes specifications for the architecture (is: x86 or is: x86_64), for VMware (vmware), and Xen (xen and domU). Add flavor specifications to your product definition to ensure certain conditions are met that aren't already specified by the abbreviated list. To do this, use the following steps:

  1. Check out your product-definition.

  2. Open the product definition XML file in a text editor.

  3. Locate the flavors defined in the file.

  4. Add the extra flavor specification to each flavor shown:

    • Select any mnemonics you need to set the appropriate condition for that flavor spec (use "~" and "!" as previously described).

    • Place the specification in the comma separated list, keeping the "is:" and architecture at the end separated only by a space from the last flavor spec before it.

  5. Check in your product-definition, and rebuild your appliance to test your new conditions.

rMake without rBuild requires a different approach

If you choose to use rMake instead of rBuild to build your appliance, rMake will not use your product definition as a guide. Instead, you will need to use flavors in your rMake build command, or define rMake contexts. For more information, see rMake documentation at the rPath Wiki.

1.2.2. Create Custom Flavor Specifications when Packaging

As a packager, you can create your own conditional statements independent from those pre-defined in your selected platform. There is an object called "Flags" from the Conary API you can use to create each new flag of your own, which in turn becomes flavor specification for your appliance.

An example of using this would be to build a single package with multiple configurations. Suppose the package example-package needs a configuration for marketing users and a different configuration for IT users. The recipe for example-package can use a conditional that identifies adding two specific configurations as well as adding a default configuration. The following is an example of such a recipe:

class ExamplePackage(PackageRecipe):
    name = 'example-package'
    version = '1.0'
    Flags.marketing = False  #default flavor is not marketing
    Flags.it = False  #default flavor is not it
 
    def setup():
       # Assert that marketing and it configurations cannot both be included
       assert not (Flags.marketing and Flags.it)
 
       # Set a macro identifying where to unpack the archive for the application
       r.macros.exampledir = '%(servicedir)s/%(name)s'
       r.addArchive('http://www.example.com/download/%(name)s_%(upver)s_install.tar.gz', 
                     dir='%(exampledir)s/')
 
       # In this example, no additional commands are required to set up the application
 
       # Include the configuration appropriate to the build flavor
        if Flags.marketing:
            r.addSource('marketing-config', dest'%(exampledir)s/config.file')
        elif Flags.it:
            r.addSource('it-config', dest'%(exampledir)s/config.file')
        else:
            r.addSource('default-config', dest'%(exampledir)s/config.file')

The following are the flavor specifications resulting from the example-package. Note that because these specifications are part of the example-package recipe class, they require "example-package" as part of each flavor specification. Add these as appropriate to the flavors in your product definition:

  • For Marketing, choose example-package.marketing, ~example-package.marketing, !example-package.marketing, or ~!example-package.marketing

  • For IT, choose example-package.it, ~example-package.it, !example-package.it, or ~!example-package.it

  • For Marketing or IT (the default), either put nothing, or explicitly use the "not" or "prefers not" for each of the two flavors specs