Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fix IMAP Folder option

Add log line display for successful input template counts
Add support for multiple outputs via munger
Remove Output/Print.pm, since it didn't work, anyway
  • Loading branch information...
commit a9b86de51b15a2f49b73714493faac1591f0f852 1 parent 5217633
Brendan Byrd authored
11 dist.ini
View
@@ -13,15 +13,12 @@ copyright_year = 2012
; Most of the coverage is more freeform
-remove = PodCoverageTests
-; DEBUG
-;-remove = Git::NextVersion
-
-
-
-x_irc = irc://irc.perl.org/#web-simple
+; Anti-CPAN stuff for now
+;x_irc = irc://irc.perl.org/#web-simple
+-remove = UploadToCPAN
; App::Daemon --> Proc::ProcessTable fails testing and hoarks this whole process
-;test_min_deps = 1
+;test_min_deps = 1
; authordep JSONY
; authordep Template::Plugin::EnvHash
95 lib/Transform/Alert.pm
View
@@ -56,33 +56,33 @@ around BUILDARGS => sub {
my $conf = $hash->{config};
my $basedir = $hash->{basedir} = $conf->{basedir};
-
+
chdir $basedir; # just go there to make relative pathing easier
# process outputs first (needed for Template sets)
$hash->{outputs} = {};
foreach my $out_key (keys %{ $conf->{output} }) {
my $out_conf = dclone $conf->{output}{$out_key};
-
+
# create the new class
my $type = delete $out_conf->{type} || die "Output '$out_key' requires a Type!";
my $class = "Transform::Alert::Output::$type";
load_class $class;
$hash->{outputs}{$out_key} = $class->new($out_conf);
}
-
+
# now process inputs
$hash->{inputs} = {};
foreach my $in_key (keys %{ $conf->{input} }) {
my $in_conf = dclone $conf->{input}{$in_key};
-
+
$in_conf->{name} = $in_key;
$in_conf->{output_objs} = $hash->{outputs};
-
+
# create the input group
$hash->{inputs}{$in_key} = Transform::Alert::InputGrp->new($in_conf);
}
-
+
$orig->($self, $hash);
};
@@ -95,7 +95,7 @@ sub BUILD {
sub heartbeat {
my $self = shift;
my $log = $self->log;
-
+
$log->debug('START Heartbeat');
foreach my $in_key (sort {
# sorting these by time_left, so that (hopefully) as much as possible is processed in one heartbeat
@@ -103,14 +103,14 @@ sub heartbeat {
} keys %{ $self->inputs }) {
$log->debug('Looking at Input "'.$in_key.'"...');
my $in = $self->inputs->{$in_key};
-
+
# are we ready for another run?
if (time > $in->last_finished + $in->interval) {
$in->process;
}
}
$log->debug('END Heartbeat');
-
+
# shut up until I'm ready...
return min map { $_->time_left } values %{ $self->inputs };
}
@@ -121,7 +121,7 @@ sub close_all {
$log->debug('Closing all I/O for ALL groups');
$_->close_all for (values %{ $self->inputs });
-
+
return 1;
}
@@ -134,24 +134,24 @@ __END__
=begin wikidoc
= SYNOPSIS
-
+
# In your configuration
BaseDir /opt/transalert
-
+
<Input test_in>
Type POP3
Interval 60 # seconds (default)
-
+
<ConnOpts>
Username bob
Password mail4fun
-
+
# See Net::POP3->new
Host mail.foobar.org
Port 110 # default
Timeout 120 # default
</ConnOpts>
-
+
<Template>
TemplateFile test_in/foo_sys_email.re
OutputName test_out
@@ -160,12 +160,12 @@ __END__
TemplateFile test_in/server01_email.re
Munger test_in/Munger.pm MyMunger->munge
OutputName test_out
- </Template>
+ </Template>
</Input>
<Output test_out>
Type Syslog
TemplateFile outputs/test.tt
-
+
# See Net::Syslog->new
<ConnOpts>
Name TransformAlert
@@ -175,12 +175,12 @@ __END__
SyslogPort 514 # default
</ConnOpts>
</Output>
-
+
# On a prompt
> transalert_ctl -c file.conf -l file.log -p file.pid
-
+
= DESCRIPTION
-
+
Ever have a need to transform one kind of alert/message into another? For example:
* Taking a bunch of alert emails and converting them into Syslogs
@@ -200,12 +200,12 @@ Or to show it with a UTF8 drawing, the platform works like this:
├── InTemplate + Munger ──┬── Output + OutTemplate
│ └── Output + OutTemplate
├── InTemplate + Munger ──┬── Output + OutTemplate
- └── InTemplate ───────────┘
+ └── InTemplate ───────────┘
Input ──┬── InTemplate ────────────── Output + OutTemplate
└── InTemplate + Munger ───── Output + OutTemplate
-
+
All [inputs|Transform::Alert::Input] and [outputs|Transform::Alert::Output] are separate modules, so if there isn't a protocol available, they
-are easy to make. Input templates use a multi-line regular expression with named captures to categorize the variables. Output templates are
+are easy to make. Input templates use a multi-line regular expression with named captures to categorize the variables. Output templates are
[TT|Template::Toolkit] templates with a {[% var %]} syntax. If you need to transform the data after it's been captured, you can use a "munger"
module to play with the variables any way you see fit.
@@ -218,16 +218,16 @@ The configuration uses an Apache-based format (via [Config::General]). There's
=== BaseDir
BaseDir [dir]
-
+
The base directory is used as a starting point for the daemon and any of the relative paths in the config file. The {BaseDir} option itself
can use a relative path, in which case will start at the config path.
-
+
=== Input
<Input [name]> # one or more
Type [type]
Interval [seconds] # optional; default is 60s
-
+
# <ConnOpts> section; module-specific
# <Template> sections
</Input>
@@ -253,10 +253,10 @@ The engine may someday be changed to have multi-processed inputs, but the need i
# Template/File can be optional
TemplateFile [file] # not used with Template
Template "[String]" # not used with TemplateFile
-
+
Munger [file] [class]->[method] # optional
OutputName test_out # one or more
- </Template>
+ </Template>
</Input>
All {Input} sections must have one or more {Template} sections. (In this case, this is an input template.) As messages are being processed,
@@ -293,29 +293,29 @@ More that one option means that the alert will be sent to multiple sources.
Type [type]
TemplateFile [file] # not used with Template
Template "[String]" # not used with TemplateFile
-
+
# <ConnOpts> section; module-specific
</Output>
Like {Input}, {Output} sections need to be uniquely named. This name is used with the {OutputName} option above. Also like {Input}, the
{Type} functions the same way (mapping to a {Transform::Alert::Output::*} class), and {ConnOpts} contains all of the module-specific options.
-Similar to {Template} sections, the {Output} section must either have a {TemplateFile} or a {Template} option. However, you can only use a
+Similar to {Template} sections, the {Output} section must either have a {TemplateFile} or a {Template} option. However, you can only use a
single template per {Output}. If you need more, use another section with most of the same options.
-
+
== Directory Structure
Depending on how large your setup is, you may want to create a directory structure like this:
/opt/transalert # config, log, PID
- /opt/transalert/input1 # various input template directories
- /opt/transalert/input2
+ /opt/transalert/input1 # various input template directories
+ /opt/transalert/input2
/opt/transalert/input3
/opt/transalert/outputs # single directory for output templates
-
+
If your set up is small, you can get away with a single directory. Just be sure to use the log/PID options in [transalert_ctl], so that they
are put in the right directory.
-
+
== Input Templates
Input templates are basically big multi-line regular expressions. These are NOT {/x} whitespace-insensitive regular expressions, as those
@@ -333,9 +333,9 @@ Here's an example using an email template:
Subject: Email Alert - \E(?<subject>[^\n]+)
Date: (?<date>[^\n]+)
[\s\S]+
-
+
We found a problem on this device:
-
+
\QName :\E (?<name>\w+)
\QProblem :\E (?<problem>[^\n]+)
\QTicket #:\E (?<ticket>\w+)
@@ -347,7 +347,7 @@ of [Mungers|/Mungers].
== Output Templates
-Output templates use [Template::Toolkit]. If you want a quick and dirty lesson on how they work, check out [Template::Manual::Syntax]. If
+Output templates use [Template::Toolkit]. If you want a quick and dirty lesson on how they work, check out [Template::Manual::Syntax]. If
*that* is too wordy for you, then just remember that variables are replaced with a {[% t.var %]} syntax.
The variables passed to the Output (or Munger, if specified) will look like this:
@@ -369,9 +369,9 @@ Here's an example output template that looks similar to the input one above:
From: [% t.from %]
Subject: Email Alert - [% t.subject %]
Date: [% t.date %]
-
+
We found a problem on this device:
-
+
Name : [% t.name %]
Problem : [% t.problem %]
Ticket #: [% t.ticket %]
@@ -379,7 +379,7 @@ Here's an example output template that looks similar to the input one above:
== Mungers
Mungers are an optional second piece to the input template structure. Regular expressions, as powerful as they are with finding and capturing
-information, only do just that. Sometimes you need to warp the information you've captured to fit the mold that the output can use. Or
+information, only do just that. Sometimes you need to warp the information you've captured to fit the mold that the output can use. Or
sometimes you need to validate the input in a better fashion than REs can provide. Mungers fit both of those roles.
Mungers are basically freeform Perl modules that transform and/or validate the input data passed to it. Here's an example munger, straight
@@ -389,9 +389,9 @@ from the test platform:
sub munge {
my ($class, $vars, $tmpl_grp) = @_;
-
+
$vars->{t}{thingy} = delete $vars->{t}{item};
-
+
return int rand(2) ? $vars : undef;
}
@@ -399,9 +399,10 @@ from the test platform:
This munger does two (useless) things: change the name of the {item} variable to {thingy}, and randomly reject the input. But, this munger
could just as easily do anything Perl can do to transform and validate the data.
-
+
All mungers are called by their class (ie: {TestMunger->munge}), so all of them should have a package name. They should also return either
-{undef} (as a rejection) or the variable list (as a hashref).
+{undef} (as a rejection) or the variable list (as a hashref). If the input ends up with multiple alerts, a munger can also pass an arrayref
+(of hashrefs), and they will be sent to the outputs individually.
A munger could also become the *primary* piece for input transformation/validation by not specifying a Template option.
@@ -419,8 +420,8 @@ This doesn't work on Windows. Blame [Proc::ProcessTable]. Or rather, [this bug
Inputs Outputs
------ -------
- HTTP::Atom
- HTTP::RSS
+ HTTP::Atom
+ HTTP::RSS
File::CSV File::CSV
File::Text File::Text
IRC
6 lib/Transform/Alert/Input/IMAP.pm
View
@@ -66,9 +66,9 @@ sub open {
$imap->login || do { $self->log->error('IMAP Login failed: ' .$imap->LastError); return; };
}
- # might not have a folder set
- unless ($imap->IsSelected) {
- $imap->select('Inbox') || do { $self->log->error('IMAP Select failed: '.$imap->LastError); return; };
+ # might not have a folder set (or might have a specific Folder option)
+ if (!$imap->IsSelected || $self->connopts->{folder}) {
+ $imap->select($self->connopts->{folder} || 'Inbox') || do { $self->log->error('IMAP Select failed: '.$imap->LastError); return; };
}
}
3  lib/Transform/Alert/InputGrp.pm
View
@@ -102,6 +102,7 @@ sub process {
$log->info(' Found message: '.printable(elide($$msg, int(2.5 ** $log->level) )) );
# start the matching process
+ my $tmpl_count = 0;
foreach my $tmpl (@{ $self->templates }) {
# input RE templates
my $vars = {};
@@ -109,11 +110,13 @@ sub process {
next unless ($$msg =~ $tmpl->regexp); # found one
$vars = { %+ }; # untie
}
+ $tmpl_count++;
$tmpl->send_all({
t => $vars,
p => $hash,
});
}
+ $log->info(' '.($tmpl_count ? $tmpl_count : 'No').' matching template'.($tmpl_count == 1 ? '' : 's').' found');
}
$self->close_all;
36 lib/Transform/Alert/Output/Print.pm
View
@@ -1,36 +0,0 @@
-package Transform::Alert::Output::Print;
-
-# VERSION
-# ABSTRACT: Transform alerts to plain text STDOUT messages
-
-use sanity;
-use Moo;
-use MooX::Types::MooseLike::Base qw(InstanceOf);
-
-with 'Transform::Alert::Output';
-
-sub open { 1 }
-sub opened { 1 }
-sub send { print $_[1]; 1; }
-sub close { 1 }
-
-42;
-
-__END__
-
-=begin wikidoc
-
-= SYNOPSIS
-
- # In your configuration
- <Output print>
- Type Print
- TemplateFile outputs/test.tt
- <ConnOpts/>
- </Output>
-
-= DESCRIPTION
-
-This output type is mainly used for testing.
-
-=end wikidoc
53 lib/Transform/Alert/TemplateGrp.pm
View
@@ -111,31 +111,36 @@ sub send_all {
$log->trace( join "\n", map { ' '.$_ } split(/\n/, pp $vars) );
}
- my $tt = Template->new();
- foreach my $out_key (keys %{ $self->outputs }) {
- $log->debug('Looking at Output "'.$out_key.'"...');
- my $out = $self->outputs->{$out_key};
- my $out_str = '';
-
- $tt->process($out->template, $vars, \$out_str) || do {
- $log->error('TT error for "$out_key": '.$tt->error);
- $log->warn('Output error... bailing out of this process cycle!');
- $self->close_all;
- return;
- };
-
- # send alert
- unless ($out->opened) {
- $log->debug('Opening output connection');
- $out->open;
- }
- $log->info('Sending alert for "'.$out_key.'"');
- $log->info(' Output message: '.printable(elide($out_str, int(2.5 ** $log->level) )) );
+ # Support multiple outputs, if the munger sent them
+ $vars = [ $vars ] unless (ref $vars eq 'ARRAY');
- unless ($out->send(\$out_str)) {
- $log->warn('Output error... bailing out of this process cycle!');
- $self->close_all;
- return;
+ my $tt = Template->new();
+ foreach my $v (@$vars) {
+ foreach my $out_key (keys %{ $self->outputs }) {
+ $log->debug('Looking at Output "'.$out_key.'"...');
+ my $out = $self->outputs->{$out_key};
+ my $out_str = '';
+
+ $tt->process($out->template, $v, \$out_str) || do {
+ $log->error('TT error for "$out_key": '.$tt->error);
+ $log->warn('Output error... bailing out of this process cycle!');
+ $self->close_all;
+ return;
+ };
+
+ # send alert
+ unless ($out->opened) {
+ $log->debug('Opening output connection');
+ $out->open;
+ }
+ $log->info('Sending alert for "'.$out_key.'"');
+ $log->info(' Output message: '.printable(elide($out_str, int(2.5 ** $log->level) )) );
+
+ unless ($out->send(\$out_str)) {
+ $log->warn('Output error... bailing out of this process cycle!');
+ $self->close_all;
+ return;
+ }
}
}
41 weaver.ini
View
@@ -2,39 +2,40 @@
[-WikiDoc]
[@CorePrep]
-
+
[Name]
-
+
[Region / prelude]
-
+
[Generic / SYNOPSIS]
[Generic / DESCRIPTION]
[Generic / OVERVIEW]
-
+
[Collect / ATTRIBUTES]
command = attr
-
+
[Collect / METHODS]
command = method
-
+
[Collect / FUNCTIONS]
command = func
[Leftovers]
-
+
[Region / postlude]
-
-[Availability]
-[Support]
-perldoc = 0
-websites = none
-repository_link = none
-bugs = metadata
-bugs_content = Please report any bugs or feature requests via L<{WEB}|GitHub>.
-irc = irc.perl.org, #web-simple, SineSwiper
-
-[Authors]
-[Legal]
-
+
+; Anti-CPAN stuff for now
+;[Availability]
+;[Support]
+;perldoc = 0
+;websites = none
+;repository_link = none
+;bugs = metadata
+;bugs_content = Please report any bugs or feature requests via L<{WEB}|GitHub>.
+;irc = irc.perl.org, #web-simple, SineSwiper
+;
+;[Authors]
+;[Legal]
+
[-Transformer]
transformer = List
Please sign in to comment.
Something went wrong with that request. Please try again.