[rt-devel] Contrib: ScripCondition Crontab
Bruce Campbell
bruce_campbell at ripe.net
Tue Feb 5 07:41:45 EST 2002
The attached ScripCondition will give the ability to perform certain
conditions at certain times of the day, utilising a format very similar to
crontab(5), hence the name.
Apart from this change, it is a plug-in replacement for the default
RT::Condition::AnyTransaction.
The time values are kept in the Argument of the ScripCondition.
Obviously, to have differing times of the day, you will need to create
different ScripConditions using different time ranges in the argument.
The attached insert_condition Template gives the default '* * * * *' (any
time).
Multiple time values can be given in one Argument, by using the ':'
character to seperate them. Multiple Transaction types can be matched by
playing with the ApplicableTransTypes field.
The main usage of this ScripCondition would be to give a different
auto-reply outside office hours.
A walkthrough of the programming of this ScripCondition will be sent to
rt-users in due course.
Regards,
--
Bruce Campbell RIPE
Systems/Network Engineer NCC
www.ripe.net - PGP562C8B1B Operations
-------------- next part --------------
# ScripCondition: Crontab.pm
# IsApplicable returns true if the current time is within the
# range specified by the Argument, undef otherwise.
# Bruce Campbell says to always give yourself Credit, and
# to use RCS (man rcs):
# $Id: Crontab.pm,v 1.3 2002/02/05 12:15:42 bc Exp $
=head1 NAME
RT::Condition::Crontab
=head1 SYNOPSIS
This is a ScripCondition to fire when 'Now' is within certain time
ranges. The Argument supplied is the standard 'crontab' format.
Multiple crontab-style time ranges can be specified by seperating
them with the ':' character.
=head1 ARGUMENT FORMAT
Crontab format is defined as 5 fields, seperated by spaces. The
specific fields are described in order as:
field allowed values
----- --------------
minute 0-59
hour 0-23
day of month 1-31
month 1-12
day of week 0-7 (0 or 7 is Sun)
Any of the fields may consist of specific numbers within the allowed
values, ranges (identified by 'start-end'), lists (seperated by
commas, eg '1,4,6,4'), steps (every 'step' value, indicated by a '/',
eg every 2nd item from 4 to 9 '4-9/2') or a wildcard ('*').
Set::Crontab also defines the following extensions:
<N and >N
Elements from the allowed range less than or greater
than 'N'.
!N
Excludes 'N' from the set.
=head1 EXAMPLES
The following matches all times between 9am and 4:59pm (close enough
to 5pm), Monday to Friday:
* 9-16 * * 1-5
The following (in the Argument) matches all times between 8:45am and 5:15pm
Monday to Friday (note the ':' seperations):
45-59 8 * * 1-5:* 9-16 * * 1-5:0-15 17 * * 1-5
=cut
# Who are we?
package RT::Condition::Crontab;
# Bring all the RT Goodness into our lives.
require RT::Condition::Generic;
# and our namespace
@ISA = qw(RT::Condition::Generic);
# We're going to use this later.
use Set::Crontab;
# Override RT::Condition::Generic's IsApplicable method:
sub IsApplicable {
# Get our OO $self.
my $self = shift;
# Prepare our default return value
my $retval = undef;
# Get the current time.
my $cur_time = new RT::Date( $RT::Nobody );
$cur_time->SetToNow();
# Split apart the multiple time ranges.
my @time_ranges = split( ':', $self->Argument );
# Prepare 'now'.
# We'll use localtime on the Unix() method of RT::Date
# This returns a @list of time components.
my @nowlist = localtime( $cur_time->Unix );
# Build up a compare list.
my @wantlist = ();
# Names are not supported in Set::Crontab
$wantlist[0] = $nowlist[1]; # minute 0-59
$wantlist[1] = $nowlist[2]; # hour 0-23
$wantlist[2] = $nowlist[3]; # day of month 1-31
$wantlist[3] = $nowlist[4] + 1; # month 1-12 (need to adjust)
$wantlist[4] = $nowlist[6]; # day of week 0-7
# What about the specific ranges?
my @known_ranges = (
[0..59], # minute 0-59
[0..23], # hour 0-23
[1..31], # day of month 1-31
[1..12], # month 1-12
[0..7], # day of week 0-7
);
# We loop through the various @time_ranges that we've found.
foreach my $this_range ( @time_ranges ){
# Remove leading or trailing space (we split() on that later)
$this_range =~ s/^\s*//g;
$this_range =~ s/\s*$//g;
# $RT::Logger->debug("$self: Range is $this_range\n");
# How many of the fields have we matched so far?
my $matched = 0;
# Split apart the fields based on whitespace.
my @this_list = split( /\s+/, $this_range );
# See if each field is in within range.
my $loop = 0;
while( ( $loop < scalar @wantlist ) && ( $loop < scalar @this_list ) ){
my $tst = Set::Crontab->new( $this_list[$loop], $known_ranges[$loop] );
# $RT::Logger->debug( "$self: Testing $wantlist[$loop] against $this_list[$loop]\n");
if( $tst->contains( $wantlist[$loop] ) ){
$matched++;
}
# Remember to increment the loop.
$loop++;
}
# Now we check to see whether we matched them all.
# If we didn't, 'now' is obviously not within this time range.
# Did we match them all?
if( ( $matched == $loop ) && ( $loop == scalar @wantlist ) ){
# We did. Set our return value.
$retval++;
}
}
# retval is undef when declared, and only incremented
# if a time value matches.
return( $retval );
}
1;
-------------- next part --------------
#!/usr/bin/perl -w
#
# $Header: /raid/cvsroot/rt-addons/ScripConditions/OnOwnerChange/insert_condition.pl,v 1.1 2001/06/17 19:18:36 jesse Exp $
# RT is (c) 1996-2000 Jesse Vincent (jesse at fsck.com);
# IncomingEmail Condition by Bruce Campbell
package RT;
use strict;
use vars qw($VERSION $Handle $Nobody $SystemUser $item);
use lib "/home/rt2/lib";
use lib "/home/rt2/etc";
#This drags in RT's config.pm
use config;
use Carp;
use RT::Handle;
use RT::User;
use RT::CurrentUser;
#connect to the db
$RT::Handle = new RT::Handle($RT::DatabaseType);
$RT::Handle->Connect();
#Put together a current user object so we can create a User object
my $CurrentUser = new RT::CurrentUser();
#now that we bootstrapped that little bit, we can use the standard RT cli
# helpers to do what we need
use RT::Interface::CLI qw(CleanEnv LoadConfig DBConnect
GetCurrentUser GetMessageContent);
#Clean out all the nasties from the environment
CleanEnv();
#Load etc/config.pm and drop privs
LoadConfig();
#Connect to the database and get RT::SystemUser and RT::Nobody loaded
DBConnect();
$CurrentUser->LoadByName('RT_System');
# {{{ ScripConditions
# The Argument is a ':' seperated list of crontab-format ranges to determine
# whether 'Now' is within the range.
my @ScripConditions = (
{
Name => 'OnCreateAnyTime',
Description => 'Matches at any point in time',
ApplicableTransTypes => 'Any',
Argument => '* * * * *',
ExecModule => 'Crontab',
},
);
# }}}
print "Creating ScripConditions...";
use RT::ScripCondition;
for $item (@ScripConditions) {
my $new_entry = new RT::ScripCondition($CurrentUser);
my $return = $new_entry->Create(%$item);
print $return.".";
}
print "done.\n";
$RT::Handle->Disconnect();
1;
More information about the Rt-devel
mailing list