Recently there have been at least two posts (Config File Shuffle and Is there such an animal as Config::Simple::VirtualHost?) about configuration management when multiple apps are involved. I answered those questions with brief pointers to Gantry::Conf. This meditation goes into more detail.

Background

A few months ago, my boss came to the bat cave and asked me to make a feature from our customer service call center application available via our customer facing web server. The backend functionality could be shared by the two applications, but that required some shared configuration information.

In another incident, at about the same time, one of our cron scripts failed because its conf was out of sync with the web application it supports.

After these conf headaches, my boss hatched a plan (which is, by itself, evidence of a severe lack of pointy hair). It went like this.

Suppose that on each system there was a single index to all conf for apps which run on that box. In the file is a list of app instances and how they are configured. Each app instance can share conf with other app instances, while having some specific conf for itself.

Finally, for any given bit of conf information there should be many ways to supply it. So, when we give you an app, you don't have to configure it like we do. We usually prefer flat files, you might like LDAP or an SQL database. The choice should belong to the installing admin.

Specifying Conf

Suppose there are two apps we need to deliver: a budgeting tool and a company phone list. The budget is delivered in two instances, providing the same functionality to both the sales and service departments. Each of the apps has a database behind it; those databases live on the same server. Here is one way to configure them:
# The configuration index is in Config::General format. # We store it in /etc/gantry.conf (the default), # but you don't have to. # Everyone shares the database_server_name, # unless their conf overrides it. <global> database_server_name ourdb.example.com </global> # This will be used by the budget application instances. # You could also put the codes in a shared file. # We are all about choice: your choice. <shared codes> petty_cash 10 travel 30 # etc. </shared> # The sales department uses the above codes and shares # the dbconf available via https with the other instances # (this has the database user name and password # for each app). # # budget_sales.conf is listed first, so it takes precedence # over everything else. It defines the database name # and anything else unique to this instance. <instance budget_sales> ConfigureVia FlatFile Config::General /etc/gantry.d/budget_sales.c +onf ConfigureVia HTTP Config::General https://confserver.example.com/d +bconf use codes </instance> # budget_service is exactly like budget_sales, except # it uses budget_service.conf to find its database # name, etc. <instance budget_service> ConfigureVia FlatFile Config::General /etc/gantry.d/budget_service +.conf ConfigureVia HTTP Config::General https://confserver.example.com/d +bconf use codes </instance> # Someone must have liked Config::Tiny at some point, # because this app needs it. <instance phone_list> ConfigureVia FlatFile Config::Tiny /etc/gantry.d/phone_list.conf ConfigureVia HTTP Config::General https://confserver.example.com/ +dbconf </instance>

Deploying Apps

Now suppose that we deploy these web apps via mod_perl.
In the root location for the app we can set a var:
<Location /budget_sales> #... PerlSetVar GantryConfInstance budget_sales </Location>
Then, in the mod_perl handler for the budget application, we can use this to retrieve our conf:
my $conf = Gantry::Conf->retrieve( { instance => $r->dir_config( 'GantryConfInstance' ) });
In fact, this is what our Gantry framework does. If our index file was not in /etc/gantry.conf, we would have added the config_file key to the parameter hash passed to retrieve:
my $conf = Gantry::Conf->retrieve( { instance => $r->dir_config( 'GantryConfInstance' ), config_file => '/etc/gantry.d/standard.conf', } );
For cgi, you could inspect the url looking for your instance, instead of using dir_config on the request object. In cron scripts we can gain the instance from the command line:
use Getopt::Long; my $instance = 'budget_default'; GetOptions( 'instance|i' => \$instance ); my $conf = Gantry::Conf->retrieve( { instance => $instance } );

We hope you enjoy Gantry::Conf as much as we do. And feel free to check out its parent project the Gantry web app frameword: http://www.usegantry.org.

If you have suggestions or comments, we want them.

Phil


In reply to Configuration Flexibility by philcrow

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.