Home | Wiki | OI 1.x Docs | OI 2.x Docs |
OpenInteract2::Manage - Provide common functions and factory for management tasks
# Common programmatic use of management task: use strict; use OpenInteract2::Manage; my $task = OpenInteract2::Manage->new( 'install_package', { filename => '/home/httpd/site/uploads/file.tar.gz', website_dir => '/home/httpd/site' } ); my @status = eval { $task->execute }; if ( $@ ) { if ( $@->isa( 'OpenInteract2::Exception::Parameter' ) ) { my $failures = $@->parameter_fail; while ( my ( $field, $reasons ) = each %{ $failures } ) { print "Field $field: ", join( ", ", @{ $reasons } ), "\n"; } } exit; } foreach my $s ( @status ) { print "Status: ", ( $s->{is_ok} eq 'yes' ) ? 'OK' : 'NOT OK'; print "\n$s->{message}\n"; } # Every task needs to implement the following: sub run_task {} sub get_parameters {} # if it has parameters # The task can implement this to initialize the object sub init {} # The task can also implement these for setting up/clearing out the # environment sub setup_task {} sub tear_down_task {} # The task can also implement this for checking/validating parameters sub validate_param {} # This task is strongly advised to implement this to let the outside # world know about its purpose sub get_brief_description {}
First, most people don't really care about this class. You'll use the
oi2_manage
front-end to this set of tasks, so you probably want to
look there if you're itching to do something quickly.
OpenInteract2::Manage is the organizer, interface and factory for tasks managing OpenInteract2. Its goal is to make these tasks runnable from anywhere, not just the command-line, and to provide output that can be parsed in a sufficiently generic format to be useful anywhere.
Since it is an organizing module it does not actually perform the tasks. You will want to see OpenInteract2::Manage::Package or OpenInteract2::Manage::Website to get closer to that metal. You can also subclass this class directly, but look first into the other subclasses as they may provide functionality to make your task easier to implement.
If you're interested in subclassing you should really read OpenInteract2::Manual::Management. It was written just for you!
new( $task_name, [ \%params, ], [ @extra_params ] )
Creates a new management task of type $task_name
. If type
$task_name
is not yet registered, the method throws an exception.
You can also pass any number of \%params
with which the management
task gets initialized (using init()
, below). These are blindly set
and not checked until you run execute()
.
All of the extra_params
are passed to init()
, which subclasses
may implement to do any additional initialization.
Returns: New management task object
is_valid_task( $task_name )
Returns: true if $task_name
is a valid task, false if not.
valid_tasks()
Query the class about what tasks are currently registered.
Returns: list of registered tasks
valid_tasks_description()
Query the class about what tasks are currently registered, plus get a brief description of each.
Returns: hashref of registered tasks (keys) and their descriptions (values).
task_parameters( $task_name )
Ask the task for $task_name
what its parameters are.
Returns: hashref with keys as parameter names and values as hashrefs with the following data:
Parameter name
Description of this parameter for this task
Set to 'yes' if the parameter is required for operation
Set to 'yes' if it's a toggled parameter
Set to 'yes' if the parameter can handle multiple values
Set to the default value for this parameter
all_parameters()
Find all parameters used by all registered tasks and get the same data
used in task_parameters
for each. The only change is that the
'description' key is not available since there's no task
context. (That is, 'website_dir' may have one meaning in one task but
another slightly different one in another.)
Returns: hashref with parameter names as keys and values the hashrefs
described in task_parameters
except with no 'description' key.
all_parameters_long_options()
Shortcut for CLI programs (like oi2_manage
...) that use
Getopt::Long. Returns an array of option specifiers
that you can send directly to the GetOptions( \%, @ )
signature. For instance, say that from all_parameters()
we get that
'website_dir' is a normal (non-boolean, non-multivalue) parameter. Its
entry would look like this:
website_dir=s
A parameter 'analyze' with 'is_boolean' set to 'yes' would simply be:
analyze
And a parameter 'package' with 'is_multivialued' set to 'yes' would be:
package=s@
Returns: list of option specifiers compatible with Getopt::Long.
find_management_tasks( @directories )
Find all management tasks under directories in @directories
and
require
them. Note that when this class is included it runs this
for every directory in @INC
, so you should only need to run it if
you add directories to @INC
(using use lib
or manually).
Returns: nothing
execute()
Runs through the methods check_parameters()
, setup_task()
,
run_task()
, tear_down_task()
.
Any of these methods can throw an exception, so it is up to you to
wrap the call to execute()
in an eval
block and examine $@
.
Returns: an arrayref of status hash references. These should include the keys 'is_ok' (set to 'yes' if the item succeeded, 'no' if not) and 'message' describing the results. Tasks may set additional items as well, all of which should be documented in the task.
You can also retrieve the status messages by calling get_status()
.
param( $key, $value )
If $key
is unspecified, returns all parameters as a hashref.
If $value
is unspecified, returns the current value set for
parameter $key
.
If both $key
and $value
are specified, sets the parameter
$key
to $value
and returns it.
Example:
$task->param( 'website_dir', '/home/httpd/test' ); $task->param( package => [ 'pkg1', 'pkg2' ] ); my $all_params = $task->param;
Another way of setting parameters is by passing them into the
constructor. The second argument (hashref) passed into the new()
call can be set to the parameters you want to use for the task. This
makes it simple to do initialization and execution in one step:
my @status = OpenInteract2::Manage->new( 'create_website', { website_dir => '/home/httpd/test' } ) ->execute();
param_copy_from( $other_task )
Copy all parameters from $other_task
into this object.
Returns: results of param()
on this object.
get_status()
Returns a list of all status messages. This won't be populated until
after you run execute()
.
Every management task should be initialized with parameters that tell the task how or where to perform its work. This parent class provides the means to ensure required parameters are defined and that they are valid. This parameter checking is very flexible so it is simple to define your own validation checks and tell them to this parent class.
The management class has a fairly simple but flexible way for you to ensure that your task gets valid parameters.
First, you can ensure that all the parameters required are defined by
the task caller. Just tag Simply create a method list_param_required()
which
returns an arrayref of parameters that require a value to be defined:
sub list_param_required { return [ 'website_dir', 'package_dir' ] }
You can also override the method check_required_parameters()
, but
this requires you to throw the exceptions yourself.
Next, you need to ensure that all the parameters are valid. There are a couple of ways to do this
check_parameters()
This method is a wrapper for a number of separate jobs: parameter initialization, required parameter checking and parameter validation.
It is called from execute()
before run_task()
is called, so any
initialization done there (like creating a
OpenInteract2::Context) hasn't been done
yet. This may force some tasks to put off validating some parameters
until run_task()
. That's an acceptable behavior for now.
It uses the 'is_required' and 'do_validate' keys of the parameter
metadata passed back from get_parameters()
.
The first action it performs is to call param_initialize()
so your
task can do any necessary parameter manipulation.
Next it checks the required parameters, which cycling through the parameters flagged with 'is_required' and ensuring that a value for each parameter exists.
Finally it validates parameters, ensuring that parameters requiring validation (those with 'is_required' or 'do_validate' toggled on) are valid.
Any errors thrown by these methods are percolated up back to the caller. Barring strange runtime errors they're going to be OpenInteract2::Exception::Parameter objects, which means the caller can do a filter as needed, displaying more pertient information:
eval { $task->execute } my $error = $@;; if ( $error ) { if ( $error->isa( 'OpenInteract2::Exception::Parameter' ) ) { print "Caught an exception with one or more paramters:\n"; my $failed = $error->parameter_fail; while ( my ( $field, $fail ) = each %{ $failed } ) { my @failures = ( ref $fail eq 'ARRAY' ) ? @{ $fail } : ( $fail ); foreach my $failure ( @failures ) { print sprintf( "%-20s-> %s\n", $field, $failure ); } } } else { print "Caught an error: $@"; } }
param_initialize()
This class implements this method to massage the 'package' parameter into a consistent format.
You may want to implement it to modify your parameters before any
checking or validation. For instance, tasks dealing with packages
typically allow you to pass in a list or a comma-separated string, or
even use a keyword to represent multiple packages. The
param_initialize()
method can change each of these into a
consistent format, allowing the task to assume it will always be
dealing with an arrayref. This is done at initialization. (You don't
have to do this, it's just an example.)
validate_param( $param_name, $param_value )
If $param_name
with $param_value
is valid return nothing,
otherwise return one or more error messages in a list. If you're a
subclass you should forward the request onto your parents via
SUPER
. See examples of this in
OpenInteract2::Manual::Management.
Every management task is observable. (See Class::Observable for what this means.) As a creator and user of a task you can add your own observers to it and receive status and progress messages from the task as it performs its work.
There are two types of standard observations posted from management tasks. This type is passed as the first argument to your observer.
status: This is a normal status message. (See STATUS MESSAGES for what this means.) The second argument passed to your observer will be the hashref representing the status message.
progress: Indicates a new stage of the process has been reached or completed. The second argument to your observer is a text message, the optional third argument is a hashref of additional information. Currently this has only one option: long may be set to 'yes', and if so the task is telling you it's about to begin a long-running process.
For an example of an observer, see oi2_manage
.
Status messages are simple hashrefs with at least three entries:
is_ok: Set to 'yes' if this a successful status, 'no' if not.
action: Name of the action.
message: Message describing the action or the error encountered.
Each message may have any number of additional entries. A common one is filename, which is used to indicate the file acted upon. Every management task should list what keys its status messages support, not including the three listed above.
Some tasks can generate a lot of status messages, so the method
merge_status_by_action
will merge all status messages with the same
action
into a single message with the keys action
(the action)
and status
(an arrayref of the collected status messages under that
action).
OpenInteract2::Manual::Management
OpenInteract2::Manage::Package
OpenInteract2::Manage::Website
Copyright (c) 2002-2003 Chris Winters. All rights reserved.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Chris Winters <chris@cwinters.com>
Generated from the OpenInteract 1.99_03 source.