NAME
App::Env - manage application specific environments
SYNOPSIS
# import environment from package1 then package2 into current
# environment
use App::Env ( $package1, $package2, \%opts );
# import an environment at your leisure
use App::Env;
App::Env::import( $package, \%opts );
# retrieve an environment but don't import it
$env = App::Env->new( $package, \%opts );
# execute a command in that environment; just as a convenience
$env->system( $command );
# exec a command in that environment; just as a convenience
$env->exec( $command );
# oh bother, just import the environment
$env->import;
# cache this environment as the default for $package
$env->cache( 1 );
# uncache this environment if it is the default for $package
$env->cache( 0 );
# generate a string compatible with the *NIX env command
$envstr = $env->str( \%opts );
# or, stringify it for (mostly) the same result
system( 'env -i $env command' );
# pretend it's a hash; read only, though
%ENV = %$env;
DESCRIPTION
App::Env presents a uniform interface to initializing environments for applications which require special environments. The code to create such environements is encapsulated in separate modules for each application suite (e.g. App::Env::MyApp), while App::Env handles the loading, merging, and caching of environments.
App::Env is probably most useful in situations where a Perl program must invoke multiple applications each of which may require an environment different and possibly incompatible from the others. The simplified interface it provides makes it useful even in less complicated situations.
Initializing Application Environments
App::Env does not itself provide the environments for applications. It relies upon application specific Perl modules to do so. Such modules provide a single entry point (envs()) which will be called by App::Env when that environment is requested. Application specific options (e.g. version) may be passed to the module.
See App::Env::Example for information on how to write such modules.
Managing Environments
In the simplest usage, App::Env can merge (import
) the application's environment directly into the current environment. For situations where multiple incompatible environments are required, it can encapsulate those as objects with convenience methods to easily run applications within those environments.
Environment Caching
By default the environmental variables returned by the application environment modules are cached. A cache entry is given a unique key which is by default generated from the module name. This key does not take into account the contents (if any) of the AppOpts hash (see below). If the application's environment changes based upon AppOpts, an attempt to load the same application with different values for AppOpts will lead to the retrieval of the first, cached environment, rather than the new environment. To avoid this, use the CacheID option to explicitly specify a unique key for environments if this will be a problem.
If multiple packages are loaded via a single call to import or new the packages will be loaded incremently in the order specified. In order to ensure a properly merged environment the packages will be loaded freshly (any caches will be ignored) and the merged environment will be cached. The cache id will by default be generated from all of the names of the environment modules invoked; this can be overridden using the CacheID option.
Site Specific Contexts
In some situations an application's environment will depend upon which host or network it is executed on. In such instances App::Env provides a means for loading an alternate application module. It does this by loading the first existant module from the following set of module names:
App::Env::$SITE::$app
App::Env::$SITE::$app
App::Env::$app
The $SITE
variable is taken from the environment variable APP_ENV_SITE if it exists, or from the Site option to the class import() function or the new() object constructor. Additionally, if the APP_ENV_SITE environemnt variable does not exist (it is not merely empty), App::Env will first attempt to load the App::Env::Site module, which can set the APP_ENV_SITE environment variable.
Take as an example the situation where an application's environment is stored in /usr/local/myapp/setup on one host and /opt/local/myapp/setup on another. One could include logic in a single App::Env::myapp
module which would recognize which file is appropriate. If there are multiple applications, this gets messy. A cleaner method is to have separate site-specific modules (e.g. App::Env::LAN1::myapp
and App::Env::LAN2::myapp
), and switch between them based upon the APP_ENV_SITE environment variable.
The logic for setting that variable might be encoded in an App::Env::Site module to transparenlty automate things:
package App::Env::Site;
my %LAN1 = map { ( $_ => 1 ) } qw( sneezy breezy queasy );
my %LAN2 = map { ( $_ => 1 ) } qw( dopey mopey ropey );
use Sys::Hostname;
if ( $LAN1{hostname()} )
{
$ENV{APP_ENV_SITE} = 'LAN1';
}
elsif ( $LAN2{hostname()} )
{
$ENV{APP_ENV_SITE} = 'LAN2';
}
1;
INTERFACE
App::Env may be used to directly import an application's environment into the current environment, in which case the non-object oriented interface will suffice.
For more complicated uses, the object oriented interface allows for manipulating multiple separate environments.
Using App::Env without objects
Application environments may be imported into the current environment either when loading App::Env or via the APP::Env::import() function.
- import
-
use App::Env ( $application, \%options ); use App::Env ( @applications, \%shared_options ); App::Env::import( $application, \%options ); App::Env::import( @applications, \%shared_options );
Import the specified applications.
Options may be applied to specific applications by grouping application names and option hashes in arrays:
use App::Env ( [ 'app1', \%app1_options ], [ 'app2', \%app2_options ], \%shared_options ); App::Env::import( [ 'app1', \%app1_options ], [ 'app2', \%app2_options ], \%shared_options );
Shared (or default) values for options may be specified in a hash passed as the last argument.
The available options are listed below. Not all options may be shared; these are noted.
- AppOpts hashref
-
This is a hash of options to pass to the
App::Env::<application>
module. Their meanings are application specific. As noted in "Caching" the caching mechanism is not keyed off of this information -- use CacheID to ensure a unique cache key.This option may not be shared.
- Force boolean
-
Don't use the cached environment for this application.
- Site
-
Specify a site. See "Application Environments" for more information
- Cache boolean
-
Cache (or don't cache) the environment. By default it is cached. If multiple environments are loaded the combination is also cached.
- CacheID
-
A unique name for the environment. The default cache key doesn't take into account anything in AppOpts. See "Caching" for more information.
When used as a shared option for multiple packages, this will be used to identify the merged environment.
- uncache
-
App::Env::uncache( App => $app, [ Site => $site ] ) App::Env::uncache( CacheID => $cacheid )
Delete the cache entry for the given application. It is currently not possible to use this interface to explicitly uncache multi-application environments if they have not been given a unique cache id. It is possible using App::Env objects.
The available options are:
- App
-
The application name. This may not be specified if CacheID is specified.
- Site
-
If the Site option was used when first loading the environment, it must be specified here in order to delete the correct cache entry. Do not specify this option if CacheID is specified.
- CacheID
-
If the CacheID option was used to provide a cache key for the cache entry, this must be specified here. Do not specify this option if App or Site are specified.
- All
-
If true uncache all of the cached environments.
Using App::Env objects
App::Env objects give greater flexibility when dealing with multiple applications with incompatible environments.
The constructor
- new
-
$env = App::Env->new( ... )
new takes the same arguments as App::Env::import and returns an App::Env object. It does not modify the environment.
Overloaded operators
App::Env overloads the %{} and "" operators. When dereferenced as a hash an App::Env object returns a hash of the environmental variables:
%ENV = %$env;
When interpolated in a string, it is replaced with a string suitable for use with the *NIX env command; see the str() method below for its format.
Methods
- cache
-
$env->cache( $cache_state );
If
$cache_state
is true, cache this environment for the application associated with $env. If$cache_state
is false and this environment is being cached, delete the cache. - env
-
# return a hashref of the entire environment (similar to %{$env}) $env_hashref = $env->env( \%options ); # return the value of a given variable in the environment $value = $env->env('variable') # return an array of values of particular variables. @env_vals = $env->env( @variable_names );
Return either the entire environment as a hashref (similar to simply using the %{} operator) or return the value of one or more variables in the environment. When called in a scalar context it will return the value of the first variable passed to it.
The available options are:
- Exclude array or scalar
-
This specifies variables to exclude from the returned environment. It may be either a single value or an array of values.
A value may be a string (for an exact match of a variable name), a regular expression created with the qr operator, or a subroutine reference. The subroutine will be passed two arguments, the variable name and its value, and should return true if the variable should be excluded, false otherwise.
- module
-
$module = $env->module;
This returns the name of the module which was used to load the environment. If multiple modules were used, the names are concatenated, seperated by the
$;
(subscript separator) character. - str
-
$envstr = $env->str( %options );
This function returns a string which may be used with the *NIX env command to set the environment. The string contains space separated
var=value
pairs, with shell magic characters escaped. The available options are:- Exclude array or scalar
-
This specifies variables to exclude from the returned environment. It may be either a single value or an array of values.
A value may be a string (for an exact match of a variable name), a regular expression created with the qr operator, or a subroutine reference. The subroutine will be passed two arguments, the variable name and its value, and should return true if the variable should be excluded, false otherwise.
It defaults to
TERMCAP
(a variable which is usually large and unnecessary).
- system
-
$env->system( $command, @args );
This runs the passed command in the environment defined by $env. It has the same argument and returned value convention as the core Perl system command.
- exec
-
$env->exec( $command, @args );
This execs the passed command in the environment defined by $env. It has the same argument and returned value convention as the core Perl exec command.
- qexec
-
$env->qexec( $command, @args );
This acts like the qx{} Perl operator. It executes the passed command in the environment defined by $env and returns its (standard) output.
EXAMPLE USAGE
- A single application
-
This is the simplest case. If you don't care if you "pollute" the current environment, then simply
use App::Env qw( PackageName );
- Two compatible applications
-
If two applications can share an environment, and you don't mind changing the current environment;
use App::Env qw( Package1 Package2 );
If you need to preserve the environment you need to be a little more circumspect.
$env = App::Env->new( qw( Package1 Package 2 ) ); $env->system( $command1, @args ); $env->system( $command2, @args );
or even
$env->system( "$command1 | $command2" );
Or,
{ local %ENV = %$env; system( $command1); }
if you prefer not to use the system method.
- Two incompatible applications
-
If two applications can't share the environment, you'll need to load them seperately:
$env1 = App::Env->new( 'Package1' ); $env2 = App::Env->new( 'Package2' ); $env1->system( $command1 ); $env2->system( $command2 );
Things are trickier if you need to construct a pipeline. That's where the *NIX env command and App::Env object stringification come into play:
system( "env -i $env1 $command1 | env -i $env2 $command2" );
This hopefully won't overfill the shell's command buffer. If you need to specify only parts of the environment, use the str method to explicitly create the arguments to the env command.
BUGS AND LIMITATIONS
No bugs have been reported.
Please report any bugs or feature requests to bug-app-env@rt.cpan.org
, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=App-Env.
SEE ALSO
appexec
AUTHOR
Diab Jerius, <djerius@cpan.org>
COPYRIGHT AND LICENSE
Copyright 2007 Smithsonian Astrophysical Observatory
This software is released under the GNU General Public License. You may find a copy at
http://www.gnu.org/licenses
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 1126:
You forgot a '=back' before '=head1'