summaryrefslogtreecommitdiffstats
path: root/extensions/Push
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/Push')
-rw-r--r--extensions/Push/Config.pm39
-rw-r--r--extensions/Push/Extension.pm876
-rwxr-xr-xextensions/Push/bin/bugzilla-pushd.pl4
-rwxr-xr-xextensions/Push/bin/nagios_push_checker.pl33
-rw-r--r--extensions/Push/lib/Admin.pm171
-rw-r--r--extensions/Push/lib/BacklogMessage.pm135
-rw-r--r--extensions/Push/lib/BacklogQueue.pm138
-rw-r--r--extensions/Push/lib/Backoff.pm82
-rw-r--r--extensions/Push/lib/Config.pm298
-rw-r--r--extensions/Push/lib/Connector.disabled/AMQP.pm344
-rw-r--r--extensions/Push/lib/Connector.disabled/ServiceNow.pm690
-rw-r--r--extensions/Push/lib/Connector/Base.pm99
-rw-r--r--extensions/Push/lib/Connector/File.pm61
-rw-r--r--extensions/Push/lib/Connector/Phabricator.pm153
-rw-r--r--extensions/Push/lib/Connector/Spark.pm228
-rw-r--r--extensions/Push/lib/Connectors.pm129
-rw-r--r--extensions/Push/lib/Constants.pm28
-rw-r--r--extensions/Push/lib/Daemon.pm87
-rw-r--r--extensions/Push/lib/Log.pm32
-rw-r--r--extensions/Push/lib/LogEntry.pm42
-rw-r--r--extensions/Push/lib/Logger.pm50
-rw-r--r--extensions/Push/lib/Message.pm72
-rw-r--r--extensions/Push/lib/Option.pm32
-rw-r--r--extensions/Push/lib/Push.pm434
-rw-r--r--extensions/Push/lib/Queue.pm71
-rw-r--r--extensions/Push/lib/Serialise.pm427
-rw-r--r--extensions/Push/lib/Util.pm165
-rw-r--r--extensions/Push/template/en/default/setup/strings.txt.pl4
28 files changed, 2389 insertions, 2535 deletions
diff --git a/extensions/Push/Config.pm b/extensions/Push/Config.pm
index 59b78d5a2..9ca73815a 100644
--- a/extensions/Push/Config.pm
+++ b/extensions/Push/Config.pm
@@ -14,39 +14,14 @@ use warnings;
use constant NAME => 'Push';
use constant REQUIRED_MODULES => [
- {
- package => 'Daemon-Generic',
- module => 'Daemon::Generic',
- version => '0'
- },
- {
- package => 'JSON-XS',
- module => 'JSON::XS',
- version => '2.0'
- },
- {
- package => 'Crypt-CBC',
- module => 'Crypt::CBC',
- version => '0'
- },
- {
- package => 'Crypt-DES',
- module => 'Crypt::DES',
- version => '0'
- },
- {
- package => 'Crypt-DES_EDE3',
- module => 'Crypt::DES_EDE3',
- version => '0'
- },
+ {package => 'Daemon-Generic', module => 'Daemon::Generic', version => '0'},
+ {package => 'JSON-XS', module => 'JSON::XS', version => '2.0'},
+ {package => 'Crypt-CBC', module => 'Crypt::CBC', version => '0'},
+ {package => 'Crypt-DES', module => 'Crypt::DES', version => '0'},
+ {package => 'Crypt-DES_EDE3', module => 'Crypt::DES_EDE3', version => '0'},
];
-use constant OPTIONAL_MODULES => [
- {
- package => 'XML-Simple',
- module => 'XML::Simple',
- version => '0'
- },
-];
+use constant OPTIONAL_MODULES =>
+ [{package => 'XML-Simple', module => 'XML::Simple', version => '0'},];
__PACKAGE__->NAME;
diff --git a/extensions/Push/Extension.pm b/extensions/Push/Extension.pm
index f682dea35..4b60dcb73 100644
--- a/extensions/Push/Extension.pm
+++ b/extensions/Push/Extension.pm
@@ -38,18 +38,18 @@ $Carp::CarpInternal{'CGI::Carp'} = 1;
#
BEGIN {
- *Bugzilla::push_ext = \&_get_instance;
+ *Bugzilla::push_ext = \&_get_instance;
}
sub _get_instance {
- my $cache = Bugzilla->request_cache;
- if (!$cache->{'push.instance'}) {
- my $instance = Bugzilla::Extension::Push::Push->new();
- $cache->{'push.instance'} = $instance;
- $instance->logger(Bugzilla::Extension::Push::Logger->new());
- $instance->connectors(Bugzilla::Extension::Push::Connectors->new());
- }
- return $cache->{'push.instance'};
+ my $cache = Bugzilla->request_cache;
+ if (!$cache->{'push.instance'}) {
+ my $instance = Bugzilla::Extension::Push::Push->new();
+ $cache->{'push.instance'} = $instance;
+ $instance->logger(Bugzilla::Extension::Push::Logger->new());
+ $instance->connectors(Bugzilla::Extension::Push::Connectors->new());
+ }
+ return $cache->{'push.instance'};
}
#
@@ -57,22 +57,23 @@ sub _get_instance {
#
sub _enabled {
- my ($self) = @_;
- if (!exists $self->{'enabled'}) {
- my $push = Bugzilla->push_ext;
- $self->{'enabled'} = $push->config->{enabled} eq 'Enabled';
- if ($self->{'enabled'}) {
- # if no connectors are enabled, no need to push anything
- $self->{'enabled'} = 0;
- foreach my $connector (Bugzilla->push_ext->connectors->list) {
- if ($connector->enabled) {
- $self->{'enabled'} = 1;
- last;
- }
- }
+ my ($self) = @_;
+ if (!exists $self->{'enabled'}) {
+ my $push = Bugzilla->push_ext;
+ $self->{'enabled'} = $push->config->{enabled} eq 'Enabled';
+ if ($self->{'enabled'}) {
+
+ # if no connectors are enabled, no need to push anything
+ $self->{'enabled'} = 0;
+ foreach my $connector (Bugzilla->push_ext->connectors->list) {
+ if ($connector->enabled) {
+ $self->{'enabled'} = 1;
+ last;
}
+ }
}
- return $self->{'enabled'};
+ }
+ return $self->{'enabled'};
}
#
@@ -80,191 +81,186 @@ sub _enabled {
#
sub _object_created {
- my ($self, $args) = @_;
+ my ($self, $args) = @_;
- my $object = _get_object_from_args($args);
- return unless $object;
- return unless _should_push($object);
+ my $object = _get_object_from_args($args);
+ return unless $object;
+ return unless _should_push($object);
- $self->_push_object('create', $object, change_set_id(), { timestamp => $args->{'timestamp'} });
+ $self->_push_object('create', $object, change_set_id(),
+ {timestamp => $args->{'timestamp'}});
}
sub _object_modified {
- my ($self, $args) = @_;
-
- my $object = _get_object_from_args($args);
- return unless $object;
- return unless _should_push($object);
-
- my $changes = $args->{'changes'} || {};
- return unless scalar keys %$changes;
-
- my $change_set = change_set_id();
-
- # detect when a bug changes from public to private (or back), so connectors
- # can remove now-private bugs if required.
- if ($object->isa('Bugzilla::Bug')) {
- # we can't use user->can_see_bug(old_bug) as that works on IDs, and the
- # bug has already been updated, so for now assume that a bug without
- # groups is public.
- my $old_bug = $args->{'old_bug'};
- my $is_public = is_public($object);
- my $was_public = $old_bug ? !@{$old_bug->groups_in} : $is_public;
-
- if (!$is_public && $was_public) {
- # bug is changing from public to private
- # push a fake update with the just is_private change
- my $private_changes = {
- timestamp => $args->{'timestamp'},
- changes => [
- {
- field => 'is_private',
- removed => '0',
- added => '1',
- },
- ],
- };
- # note we're sending the old bug object so we don't leak any
- # security sensitive information.
- $self->_push_object('modify', $old_bug, $change_set, $private_changes);
- } elsif ($is_public && !$was_public) {
- # bug is changing from private to public
- # push a fake update with the just is_private change
- my $private_changes = {
- timestamp => $args->{'timestamp'},
- changes => [
- {
- field => 'is_private',
- removed => '1',
- added => '0',
- },
- ],
- };
- # it's ok to send the new bug state here
- $self->_push_object('modify', $object, $change_set, $private_changes);
- }
- }
+ my ($self, $args) = @_;
- # make flagtypes changes easier to process
- if (exists $changes->{'flagtypes.name'}) {
- _split_flagtypes($changes);
- }
+ my $object = _get_object_from_args($args);
+ return unless $object;
+ return unless _should_push($object);
+
+ my $changes = $args->{'changes'} || {};
+ return unless scalar keys %$changes;
- # TODO split group changes?
+ my $change_set = change_set_id();
- # restructure the changes hash
- my $changes_data = {
+ # detect when a bug changes from public to private (or back), so connectors
+ # can remove now-private bugs if required.
+ if ($object->isa('Bugzilla::Bug')) {
+
+ # we can't use user->can_see_bug(old_bug) as that works on IDs, and the
+ # bug has already been updated, so for now assume that a bug without
+ # groups is public.
+ my $old_bug = $args->{'old_bug'};
+ my $is_public = is_public($object);
+ my $was_public = $old_bug ? !@{$old_bug->groups_in} : $is_public;
+
+ if (!$is_public && $was_public) {
+
+ # bug is changing from public to private
+ # push a fake update with the just is_private change
+ my $private_changes = {
timestamp => $args->{'timestamp'},
- changes => [],
- };
- foreach my $field_name (sort keys %$changes) {
- my $new_field_name = $field_name;
- $new_field_name =~ s/isprivate/is_private/;
-
- push @{$changes_data->{'changes'}}, {
- field => $new_field_name,
- removed => $changes->{$field_name}[0],
- added => $changes->{$field_name}[1],
- };
+ changes => [{field => 'is_private', removed => '0', added => '1',},],
+ };
+
+ # note we're sending the old bug object so we don't leak any
+ # security sensitive information.
+ $self->_push_object('modify', $old_bug, $change_set, $private_changes);
}
+ elsif ($is_public && !$was_public) {
+
+ # bug is changing from private to public
+ # push a fake update with the just is_private change
+ my $private_changes = {
+ timestamp => $args->{'timestamp'},
+ changes => [{field => 'is_private', removed => '1', added => '0',},],
+ };
- $self->_push_object('modify', $object, $change_set, $changes_data);
+ # it's ok to send the new bug state here
+ $self->_push_object('modify', $object, $change_set, $private_changes);
+ }
+ }
+
+ # make flagtypes changes easier to process
+ if (exists $changes->{'flagtypes.name'}) {
+ _split_flagtypes($changes);
+ }
+
+ # TODO split group changes?
+
+ # restructure the changes hash
+ my $changes_data = {timestamp => $args->{'timestamp'}, changes => [],};
+ foreach my $field_name (sort keys %$changes) {
+ my $new_field_name = $field_name;
+ $new_field_name =~ s/isprivate/is_private/;
+
+ push @{$changes_data->{'changes'}},
+ {
+ field => $new_field_name,
+ removed => $changes->{$field_name}[0],
+ added => $changes->{$field_name}[1],
+ };
+ }
+
+ $self->_push_object('modify', $object, $change_set, $changes_data);
}
sub _get_object_from_args {
- my ($args) = @_;
- return get_first_value($args, qw(object bug flag group));
+ my ($args) = @_;
+ return get_first_value($args, qw(object bug flag group));
}
sub _should_push {
- my ($object_or_class) = @_;
- my $class = blessed($object_or_class) || $object_or_class;
- return grep { $_ eq $class } qw(Bugzilla::Bug Bugzilla::Attachment Bugzilla::Comment);
+ my ($object_or_class) = @_;
+ my $class = blessed($object_or_class) || $object_or_class;
+ return
+ grep { $_ eq $class }
+ qw(Bugzilla::Bug Bugzilla::Attachment Bugzilla::Comment);
}
# changes to bug flags are presented in a single field 'flagtypes.name' split
# into individual fields
sub _split_flagtypes {
- my ($changes) = @_;
-
- my @removed = _split_flagtype($changes->{'flagtypes.name'}->[0]);
- my @added = _split_flagtype($changes->{'flagtypes.name'}->[1]);
- delete $changes->{'flagtypes.name'};
-
- foreach my $ra (@removed, @added) {
- $changes->{$ra->[0]} = ['', ''];
- }
- foreach my $ra (@removed) {
- my ($name, $value) = @$ra;
- $changes->{$name}->[0] = $value;
- }
- foreach my $ra (@added) {
- my ($name, $value) = @$ra;
- $changes->{$name}->[1] = $value;
- }
+ my ($changes) = @_;
+
+ my @removed = _split_flagtype($changes->{'flagtypes.name'}->[0]);
+ my @added = _split_flagtype($changes->{'flagtypes.name'}->[1]);
+ delete $changes->{'flagtypes.name'};
+
+ foreach my $ra (@removed, @added) {
+ $changes->{$ra->[0]} = ['', ''];
+ }
+ foreach my $ra (@removed) {
+ my ($name, $value) = @$ra;
+ $changes->{$name}->[0] = $value;
+ }
+ foreach my $ra (@added) {
+ my ($name, $value) = @$ra;
+ $changes->{$name}->[1] = $value;
+ }
}
sub _split_flagtype {
- my ($value) = @_;
- my @result;
- foreach my $change (split(/, /, $value)) {
- my $requestee = '';
- if ($change =~ s/\(([^\)]+)\)$//) {
- $requestee = $1;
- }
- my ($name, $value) = $change =~ /^(.+)(.)$/;
- $value .= " ($requestee)" if $requestee;
- push @result, [ "flag.$name", $value ];
+ my ($value) = @_;
+ my @result;
+ foreach my $change (split(/, /, $value)) {
+ my $requestee = '';
+ if ($change =~ s/\(([^\)]+)\)$//) {
+ $requestee = $1;
}
- return @result;
+ my ($name, $value) = $change =~ /^(.+)(.)$/;
+ $value .= " ($requestee)" if $requestee;
+ push @result, ["flag.$name", $value];
+ }
+ return @result;
}
# changes to attachment flags come in via flag_end_of_update which has a
# completely different structure for reporting changes than
# object_end_of_update. this morphs flag to object updates.
sub _morph_flag_updates {
- my ($args) = @_;
-
- my @removed = _morph_flag_update($args->{'old_flags'});
- my @added = _morph_flag_update($args->{'new_flags'});
-
- my $changes = {};
- foreach my $ra (@removed, @added) {
- $changes->{$ra->[0]} = ['', ''];
- }
- foreach my $ra (@removed) {
- my ($name, $value) = @$ra;
- $changes->{$name}->[0] = $value;
- }
- foreach my $ra (@added) {
- my ($name, $value) = @$ra;
- $changes->{$name}->[1] = $value;
- }
-
- foreach my $flag (keys %$changes) {
- if ($changes->{$flag}->[0] eq $changes->{$flag}->[1]) {
- delete $changes->{$flag};
- }
+ my ($args) = @_;
+
+ my @removed = _morph_flag_update($args->{'old_flags'});
+ my @added = _morph_flag_update($args->{'new_flags'});
+
+ my $changes = {};
+ foreach my $ra (@removed, @added) {
+ $changes->{$ra->[0]} = ['', ''];
+ }
+ foreach my $ra (@removed) {
+ my ($name, $value) = @$ra;
+ $changes->{$name}->[0] = $value;
+ }
+ foreach my $ra (@added) {
+ my ($name, $value) = @$ra;
+ $changes->{$name}->[1] = $value;
+ }
+
+ foreach my $flag (keys %$changes) {
+ if ($changes->{$flag}->[0] eq $changes->{$flag}->[1]) {
+ delete $changes->{$flag};
}
+ }
- $args->{'changes'} = $changes;
+ $args->{'changes'} = $changes;
}
sub _morph_flag_update {
- my ($values) = @_;
- my @result;
- foreach my $orig_change (@$values) {
- my $change = $orig_change; # work on a copy
- $change =~ s/^[^:]+://;
- my $requestee = '';
- if ($change =~ s/\(([^\)]+)\)$//) {
- $requestee = $1;
- }
- my ($name, $value) = $change =~ /^(.+)(.)$/;
- $value .= " ($requestee)" if $requestee;
- push @result, [ "flag.$name", $value ];
+ my ($values) = @_;
+ my @result;
+ foreach my $orig_change (@$values) {
+ my $change = $orig_change; # work on a copy
+ $change =~ s/^[^:]+://;
+ my $requestee = '';
+ if ($change =~ s/\(([^\)]+)\)$//) {
+ $requestee = $1;
}
- return @result;
+ my ($name, $value) = $change =~ /^(.+)(.)$/;
+ $value .= " ($requestee)" if $requestee;
+ push @result, ["flag.$name", $value];
+ }
+ return @result;
}
#
@@ -272,49 +268,52 @@ sub _morph_flag_update {
#
sub _push_object {
- my ($self, $message_type, $object, $change_set, $changes) = @_;
- my $rh;
-
- # serialise the object
- my ($rh_object, $name) = Bugzilla::Extension::Push::Serialise->instance->object_to_hash($object);
-
- if (!$rh_object) {
- warn "empty hash from serialiser ($message_type $object)\n";
- return;
- }
- $rh->{$name} = $rh_object;
-
- # add in the events hash
- my $rh_event = Bugzilla::Extension::Push::Serialise->instance->changes_to_event($changes);
- return unless $rh_event;
- $rh_event->{'action'} = $message_type;
- $rh_event->{'target'} = $name;
- $rh_event->{'change_set'} = $change_set;
- $rh_event->{'routing_key'} = "$name.$message_type";
- if (exists $rh_event->{'changes'}) {
- $rh_event->{'routing_key'} .= ':' . join(',', map { $_->{'field'} } @{$rh_event->{'changes'}});
- }
- $rh->{'event'} = $rh_event;
-
- # create message object
- my $message = Bugzilla::Extension::Push::Message->new_transient({
- payload => to_json($rh),
- change_set => $change_set,
- routing_key => $rh_event->{'routing_key'},
- });
-
- # don't hit the database unless there are interested connectors
- my $should_push = 0;
- foreach my $connector (Bugzilla->push_ext->connectors->list) {
- next unless $connector->enabled;
- next unless $connector->should_send($message);
- $should_push = 1;
- last;
- }
- return unless $should_push;
-
- # insert into push table
- $message->create_from_transient();
+ my ($self, $message_type, $object, $change_set, $changes) = @_;
+ my $rh;
+
+ # serialise the object
+ my ($rh_object, $name)
+ = Bugzilla::Extension::Push::Serialise->instance->object_to_hash($object);
+
+ if (!$rh_object) {
+ warn "empty hash from serialiser ($message_type $object)\n";
+ return;
+ }
+ $rh->{$name} = $rh_object;
+
+ # add in the events hash
+ my $rh_event
+ = Bugzilla::Extension::Push::Serialise->instance->changes_to_event($changes);
+ return unless $rh_event;
+ $rh_event->{'action'} = $message_type;
+ $rh_event->{'target'} = $name;
+ $rh_event->{'change_set'} = $change_set;
+ $rh_event->{'routing_key'} = "$name.$message_type";
+ if (exists $rh_event->{'changes'}) {
+ $rh_event->{'routing_key'}
+ .= ':' . join(',', map { $_->{'field'} } @{$rh_event->{'changes'}});
+ }
+ $rh->{'event'} = $rh_event;
+
+ # create message object
+ my $message = Bugzilla::Extension::Push::Message->new_transient({
+ payload => to_json($rh),
+ change_set => $change_set,
+ routing_key => $rh_event->{'routing_key'},
+ });
+
+ # don't hit the database unless there are interested connectors
+ my $should_push = 0;
+ foreach my $connector (Bugzilla->push_ext->connectors->list) {
+ next unless $connector->enabled;
+ next unless $connector->should_send($message);
+ $should_push = 1;
+ last;
+ }
+ return unless $should_push;
+
+ # insert into push table
+ $message->create_from_transient();
}
#
@@ -322,104 +321,113 @@ sub _push_object {
#
sub object_end_of_create {
- my ($self, $args) = @_;
- return unless $self->_enabled;
-
- # it's better to process objects from a non-generic end_of_create where
- # possible; don't process them here to avoid duplicate messages
- my $object = _get_object_from_args($args);
- return if !$object ||
- $object->isa('Bugzilla::Bug') ||
- blessed($object) =~ /^Bugzilla::Extension/;
-
- $self->_object_created($args);
+ my ($self, $args) = @_;
+ return unless $self->_enabled;
+
+ # it's better to process objects from a non-generic end_of_create where
+ # possible; don't process them here to avoid duplicate messages
+ my $object = _get_object_from_args($args);
+ return
+ if !$object
+ || $object->isa('Bugzilla::Bug')
+ || blessed($object) =~ /^Bugzilla::Extension/;
+
+ $self->_object_created($args);
}
sub object_end_of_update {
- my ($self, $args) = @_;
+ my ($self, $args) = @_;
- # User objects are updated with every page load (to touch the session
- # token). Because we ignore user objects, there's no need to create an
- # instance of Push to check if we're enabled.
- my $object = _get_object_from_args($args);
- return if !$object || $object->isa('Bugzilla::User');
+ # User objects are updated with every page load (to touch the session
+ # token). Because we ignore user objects, there's no need to create an
+ # instance of Push to check if we're enabled.
+ my $object = _get_object_from_args($args);
+ return if !$object || $object->isa('Bugzilla::User');
- return unless $self->_enabled;
+ return unless $self->_enabled;
- # it's better to process objects from a non-generic end_of_update where
- # possible; don't process them here to avoid duplicate messages
- return if $object->isa('Bugzilla::Bug') ||
- $object->isa('Bugzilla::Flag') ||
- blessed($object) =~ /^Bugzilla::Extension/;
+ # it's better to process objects from a non-generic end_of_update where
+ # possible; don't process them here to avoid duplicate messages
+ return
+ if $object->isa('Bugzilla::Bug')
+ || $object->isa('Bugzilla::Flag')
+ || blessed($object) =~ /^Bugzilla::Extension/;
- $self->_object_modified($args);
+ $self->_object_modified($args);
}
# process bugs once they are fully formed
# object_end_of_update is triggered while a bug is being created
sub bug_end_of_create {
- my ($self, $args) = @_;
- return unless $self->_enabled;
- $self->_object_created($args);
+ my ($self, $args) = @_;
+ return unless $self->_enabled;
+ $self->_object_created($args);
}
sub bug_end_of_update {
- my ($self, $args) = @_;
- return unless $self->_enabled;
- $self->_object_modified($args);
+ my ($self, $args) = @_;
+ return unless $self->_enabled;
+ $self->_object_modified($args);
}
sub flag_end_of_update {
- my ($self, $args) = @_;
- return unless $self->_enabled;
- _morph_flag_updates($args);
- $self->_object_modified($args);
- delete $args->{changes};
+ my ($self, $args) = @_;
+ return unless $self->_enabled;
+ _morph_flag_updates($args);
+ $self->_object_modified($args);
+ delete $args->{changes};
}
# comments in bugzilla 4.0 doesn't aren't included in the bug_end_of_* hooks,
# this code uses custom hooks to trigger
sub bug_comment_create {
- my ($self, $args) = @_;
- return unless $self->_enabled;
+ my ($self, $args) = @_;
+ return unless $self->_enabled;
- return unless _should_push('Bugzilla::Comment');
- my $bug = $args->{'bug'} or return;
- my $timestamp = $args->{'timestamp'} or return;
+ return unless _should_push('Bugzilla::Comment');
+ my $bug = $args->{'bug'} or return;
+ my $timestamp = $args->{'timestamp'} or return;
- my $comments = Bugzilla::Comment->match({ bug_id => $bug->id, bug_when => $timestamp });
+ my $comments
+ = Bugzilla::Comment->match({bug_id => $bug->id, bug_when => $timestamp});
- foreach my $comment (@$comments) {
- if ($comment->body ne '') {
- $self->_push_object('create', $comment, change_set_id(), { timestamp => $timestamp });
- }
+ foreach my $comment (@$comments) {
+ if ($comment->body ne '') {
+ $self->_push_object('create', $comment, change_set_id(),
+ {timestamp => $timestamp});
}
+ }
}
sub bug_comment_update {
- my ($self, $args) = @_;
- return unless $self->_enabled;
-
- return unless _should_push('Bugzilla::Comment');
- my $bug = $args->{'bug'} or return;
- my $timestamp = $args->{'timestamp'} or return;
-
- my $comment_id = $args->{'comment_id'};
- if ($comment_id) {
- # XXX this should set changes. only is_private changes will trigger this event
- my $comment = Bugzilla::Comment->new($comment_id);
- $self->_push_object('update', $comment, change_set_id(), { timestamp => $timestamp });
-
- } else {
- # when a bug is created, an update is also triggered; we don't want to sent
- # update messages for the initial comment, or for empty comments
- my $comments = Bugzilla::Comment->match({ bug_id => $bug->id, bug_when => $timestamp });
- foreach my $comment (@$comments) {
- if ($comment->body ne '' && $comment->count) {
- $self->_push_object('create', $comment, change_set_id(), { timestamp => $timestamp });
- }
- }
+ my ($self, $args) = @_;
+ return unless $self->_enabled;
+
+ return unless _should_push('Bugzilla::Comment');
+ my $bug = $args->{'bug'} or return;
+ my $timestamp = $args->{'timestamp'} or return;
+
+ my $comment_id = $args->{'comment_id'};
+ if ($comment_id) {
+
+ # XXX this should set changes. only is_private changes will trigger this event
+ my $comment = Bugzilla::Comment->new($comment_id);
+ $self->_push_object('update', $comment, change_set_id(),
+ {timestamp => $timestamp});
+
+ }
+ else {
+ # when a bug is created, an update is also triggered; we don't want to sent
+ # update messages for the initial comment, or for empty comments
+ my $comments
+ = Bugzilla::Comment->match({bug_id => $bug->id, bug_when => $timestamp});
+ foreach my $comment (@$comments) {
+ if ($comment->body ne '' && $comment->count) {
+ $self->_push_object('create', $comment, change_set_id(),
+ {timestamp => $timestamp});
+ }
}
+ }
}
#
@@ -427,36 +435,30 @@ sub bug_comment_update {
#
sub page_before_template {
- my ($self, $args) = @_;
- my $page = $args->{'page_id'};
- my $vars = $args->{'vars'};
-
- if ($page eq 'push_config.html') {
- Bugzilla->user->in_group('admin')
- || ThrowUserError('auth_failure',
- { group => 'admin',
- action => 'access',
- object => 'administrative_pages' });
- admin_config($vars);
-
- } elsif ($page eq 'push_queues.html'
- || $page eq 'push_queues_view.html'
- ) {
- Bugzilla->user->in_group('admin')
- || ThrowUserError('auth_failure',
- { group => 'admin',
- action => 'access',
- object => 'administrative_pages' });
- admin_queues($vars, $page);
-
- } elsif ($page eq 'push_log.html') {
- Bugzilla->user->in_group('admin')
- || ThrowUserError('auth_failure',
- { group => 'admin',
- action => 'access',
- object => 'administrative_pages' });
- admin_log($vars);
- }
+ my ($self, $args) = @_;
+ my $page = $args->{'page_id'};
+ my $vars = $args->{'vars'};
+
+ if ($page eq 'push_config.html') {
+ Bugzilla->user->in_group('admin')
+ || ThrowUserError('auth_failure',
+ {group => 'admin', action => 'access', object => 'administrative_pages'});
+ admin_config($vars);
+
+ }
+ elsif ($page eq 'push_queues.html' || $page eq 'push_queues_view.html') {
+ Bugzilla->user->in_group('admin')
+ || ThrowUserError('auth_failure',
+ {group => 'admin', action => 'access', object => 'administrative_pages'});
+ admin_queues($vars, $page);
+
+ }
+ elsif ($page eq 'push_log.html') {
+ Bugzilla->user->in_group('admin')
+ || ThrowUserError('auth_failure',
+ {group => 'admin', action => 'access', object => 'administrative_pages'});
+ admin_log($vars);
+ }
}
#
@@ -464,196 +466,86 @@ sub page_before_template {
#
sub db_schema_abstract_schema {
- my ($self, $args) = @_;
- $args->{'schema'}->{'push'} = {
- FIELDS => [
- id => {
- TYPE => 'MEDIUMSERIAL',
- NOTNULL => 1,
- PRIMARYKEY => 1,
- },
- push_ts => {
- TYPE => 'DATETIME',
- NOTNULL => 1,
- },
- payload => {
- TYPE => 'LONGTEXT',
- NOTNULL => 1,
- },
- change_set => {
- TYPE => 'VARCHAR(32)',
- NOTNULL => 1,
- },
- routing_key => {
- TYPE => 'VARCHAR(64)',
- NOTNULL => 1,
- },
- ],
- };
- $args->{'schema'}->{'push_backlog'} = {
- FIELDS => [
- id => {
- TYPE => 'MEDIUMSERIAL',
- NOTNULL => 1,
- PRIMARYKEY => 1,
- },
- message_id => {
- TYPE => 'INT3',
- NOTNULL => 1,
- },
- push_ts => {
- TYPE => 'DATETIME',
- NOTNULL => 1,
- },
- payload => {
- TYPE => 'LONGTEXT',
- NOTNULL => 1,
- },
- change_set => {
- TYPE => 'VARCHAR(32)',
- NOTNULL => 1,
- },
- routing_key => {
- TYPE => 'VARCHAR(64)',
- NOTNULL => 1,
- },
- connector => {
- TYPE => 'VARCHAR(32)',
- NOTNULL => 1,
- },
- attempt_ts => {
- TYPE => 'DATETIME',
- },
- attempts => {
- TYPE => 'INT2',
- NOTNULL => 1,
- },
- last_error => {
- TYPE => 'MEDIUMTEXT',
- },
- ],
- INDEXES => [
- push_backlog_idx => {
- FIELDS => ['message_id', 'connector'],
- TYPE => 'UNIQUE',
- },
- ],
- };
- $args->{'schema'}->{'push_backoff'} = {
- FIELDS => [
- id => {
- TYPE => 'MEDIUMSERIAL',
- NOTNULL => 1,
- PRIMARYKEY => 1,
- },
- connector => {
- TYPE => 'VARCHAR(32)',
- NOTNULL => 1,
- },
- next_attempt_ts => {
- TYPE => 'DATETIME',
- },
- attempts => {
- TYPE => 'INT2',
- NOTNULL => 1,
- },
- ],
- INDEXES => [
- push_backoff_idx => {
- FIELDS => ['connector'],
- TYPE => 'UNIQUE',
- },
- ],
- };
- $args->{'schema'}->{'push_options'} = {
- FIELDS => [
- id => {
- TYPE => 'MEDIUMSERIAL',
- NOTNULL => 1,
- PRIMARYKEY => 1,
- },
- connector => {
- TYPE => 'VARCHAR(32)',
- NOTNULL => 1,
- },
- option_name => {
- TYPE => 'VARCHAR(32)',
- NOTNULL => 1,
- },
- option_value => {
- TYPE => 'VARCHAR(255)',
- NOTNULL => 1,
- },
- ],
- INDEXES => [
- push_options_idx => {
- FIELDS => ['connector', 'option_name'],
- TYPE => 'UNIQUE',
- },
- ],
- };
- $args->{'schema'}->{'push_log'} = {
- FIELDS => [
- id => {
- TYPE => 'MEDIUMSERIAL',
- NOTNULL => 1,
- PRIMARYKEY => 1,
- },
- message_id => {
- TYPE => 'INT3',
- NOTNULL => 1,
- },
- change_set => {
- TYPE => 'VARCHAR(32)',
- NOTNULL => 1,
- },
- routing_key => {
- TYPE => 'VARCHAR(64)',
- NOTNULL => 1,
- },
- connector => {
- TYPE => 'VARCHAR(32)',
- NOTNULL => 1,
- },
- push_ts => {
- TYPE => 'DATETIME',
- NOTNULL => 1,
- },
- processed_ts => {
- TYPE => 'DATETIME',
- NOTNULL => 1,
- },
- result => {
- TYPE => 'INT1',
- NOTNULL => 1,
- },
- data => {
- TYPE => 'MEDIUMTEXT',
- },
- ],
- };
+ my ($self, $args) = @_;
+ $args->{'schema'}->{'push'} = {
+ FIELDS => [
+ id => {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1,},
+ push_ts => {TYPE => 'DATETIME', NOTNULL => 1,},
+ payload => {TYPE => 'LONGTEXT', NOTNULL => 1,},
+ change_set => {TYPE => 'VARCHAR(32)', NOTNULL => 1,},
+ routing_key => {TYPE => 'VARCHAR(64)', NOTNULL => 1,},
+ ],
+ };
+ $args->{'schema'}->{'push_backlog'} = {
+ FIELDS => [
+ id => {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1,},
+ message_id => {TYPE => 'INT3', NOTNULL => 1,},
+ push_ts => {TYPE => 'DATETIME', NOTNULL => 1,},
+ payload => {TYPE => 'LONGTEXT', NOTNULL => 1,},
+ change_set => {TYPE => 'VARCHAR(32)', NOTNULL => 1,},
+ routing_key => {TYPE => 'VARCHAR(64)', NOTNULL => 1,},
+ connector => {TYPE => 'VARCHAR(32)', NOTNULL => 1,},
+ attempt_ts => {TYPE => 'DATETIME',},
+ attempts => {TYPE => 'INT2', NOTNULL => 1,},
+ last_error => {TYPE => 'MEDIUMTEXT',},
+ ],
+ INDEXES => [
+ push_backlog_idx => {FIELDS => ['message_id', 'connector'], TYPE => 'UNIQUE',},
+ ],
+ };
+ $args->{'schema'}->{'push_backoff'} = {
+ FIELDS => [
+ id => {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1,},
+ connector => {TYPE => 'VARCHAR(32)', NOTNULL => 1,},
+ next_attempt_ts => {TYPE => 'DATETIME',},
+ attempts => {TYPE => 'INT2', NOTNULL => 1,},
+ ],
+ INDEXES => [push_backoff_idx => {FIELDS => ['connector'], TYPE => 'UNIQUE',},],
+ };
+ $args->{'schema'}->{'push_options'} = {
+ FIELDS => [
+ id => {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1,},
+ connector => {TYPE => 'VARCHAR(32)', NOTNULL => 1,},
+ option_name => {TYPE => 'VARCHAR(32)', NOTNULL => 1,},
+ option_value => {TYPE => 'VARCHAR(255)', NOTNULL => 1,},
+ ],
+ INDEXES => [
+ push_options_idx => {FIELDS => ['connector', 'option_name'], TYPE => 'UNIQUE',},
+ ],
+ };
+ $args->{'schema'}->{'push_log'} = {
+ FIELDS => [
+ id => {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1,},
+ message_id => {TYPE => 'INT3', NOTNULL => 1,},
+ change_set => {TYPE => 'VARCHAR(32)', NOTNULL => 1,},
+ routing_key => {TYPE => 'VARCHAR(64)', NOTNULL => 1,},
+ connector => {TYPE => 'VARCHAR(32)', NOTNULL => 1,},
+ push_ts => {TYPE => 'DATETIME', NOTNULL => 1,},
+ processed_ts => {TYPE => 'DATETIME', NOTNULL => 1,},
+ result => {TYPE => 'INT1', NOTNULL => 1,},
+ data => {TYPE => 'MEDIUMTEXT',},
+ ],
+ };
}
sub install_filesystem {
- my ($self, $args) = @_;
- my $files = $args->{'files'};
+ my ($self, $args) = @_;
+ my $files = $args->{'files'};
- my $extensionsdir = bz_locations()->{'extensionsdir'};
- my $scriptname = $extensionsdir . "/Push/bin/bugzilla-pushd.pl";
+ my $extensionsdir = bz_locations()->{'extensionsdir'};
+ my $scriptname = $extensionsdir . "/Push/bin/bugzilla-pushd.pl";
- $files->{$scriptname} = {
- perms => Bugzilla::Install::Filesystem::WS_EXECUTE
- };
+ $files->{$scriptname} = {perms => Bugzilla::Install::Filesystem::WS_EXECUTE};
}
sub db_sanitize {
- my $dbh = Bugzilla->dbh;
- print "Deleting push extension logs and messages...\n";
- $dbh->do("DELETE FROM push");
- $dbh->do("DELETE FROM push_backlog");
- $dbh->do("DELETE FROM push_backoff");
- $dbh->do("DELETE FROM push_log");
- $dbh->do("DELETE FROM push_options");
+ my $dbh = Bugzilla->dbh;
+ print "Deleting push extension logs and messages...\n";
+ $dbh->do("DELETE FROM push");
+ $dbh->do("DELETE FROM push_backlog");
+ $dbh->do("DELETE FROM push_backoff");
+ $dbh->do("DELETE FROM push_log");
+ $dbh->do("DELETE FROM push_options");
}
__PACKAGE__->NAME;
diff --git a/extensions/Push/bin/bugzilla-pushd.pl b/extensions/Push/bin/bugzilla-pushd.pl
index 47c905558..cc509aa45 100755
--- a/extensions/Push/bin/bugzilla-pushd.pl
+++ b/extensions/Push/bin/bugzilla-pushd.pl
@@ -14,8 +14,8 @@ use 5.10.1;
use lib qw(. lib local/lib/perl5);
BEGIN {
- use Bugzilla;
- Bugzilla->extensions;
+ use Bugzilla;
+ Bugzilla->extensions;
}
use Bugzilla::Extension::Push::Daemon;
diff --git a/extensions/Push/bin/nagios_push_checker.pl b/extensions/Push/bin/nagios_push_checker.pl
index b578c33d2..4e6e94167 100755
--- a/extensions/Push/bin/nagios_push_checker.pl
+++ b/extensions/Push/bin/nagios_push_checker.pl
@@ -20,15 +20,14 @@ Bugzilla->usage_mode(USAGE_MODE_CMDLINE);
# Number of jobs required in the queue before we alert
-use constant WARN_COUNT => 500;
-use constant ALARM_COUNT => 750;
+use constant WARN_COUNT => 500;
+use constant ALARM_COUNT => 750;
-use constant NAGIOS_OK => 0;
-use constant NAGIOS_WARNING => 1;
-use constant NAGIOS_CRITICAL => 2;
+use constant NAGIOS_OK => 0;
+use constant NAGIOS_WARNING => 1;
+use constant NAGIOS_CRITICAL => 2;
-my $connector = shift
- || die "Syntax: $0 connector\neg. $0 TCL\n";
+my $connector = shift || die "Syntax: $0 connector\neg. $0 TCL\n";
$connector = uc($connector);
my $sql = <<EOF;
@@ -38,15 +37,17 @@ my $sql = <<EOF;
EOF
my $dbh = Bugzilla->switch_to_shadow_db;
-my ($count) = @{ $dbh->selectcol_arrayref($sql, undef, $connector) };
+my ($count) = @{$dbh->selectcol_arrayref($sql, undef, $connector)};
if ($count < WARN_COUNT) {
- print "push $connector OK: $count messages found.\n";
- exit NAGIOS_OK;
-} elsif ($count < ALARM_COUNT) {
- print "push $connector WARNING: $count messages found.\n";
- exit NAGIOS_WARNING;
-} else {
- print "push $connector CRITICAL: $count messages found.\n";
- exit NAGIOS_CRITICAL;
+ print "push $connector OK: $count messages found.\n";
+ exit NAGIOS_OK;
+}
+elsif ($count < ALARM_COUNT) {
+ print "push $connector WARNING: $count messages found.\n";
+ exit NAGIOS_WARNING;
+}
+else {
+ print "push $connector CRITICAL: $count messages found.\n";
+ exit NAGIOS_CRITICAL;
}
diff --git a/extensions/Push/lib/Admin.pm b/extensions/Push/lib/Admin.pm
index 9df2bddcb..d86d30a62 100644
--- a/extensions/Push/lib/Admin.pm
+++ b/extensions/Push/lib/Admin.pm
@@ -19,110 +19,109 @@ use Bugzilla::Util qw(trim detaint_natural trick_taint);
use base qw(Exporter);
our @EXPORT = qw(
- admin_config
- admin_queues
- admin_log
+ admin_config
+ admin_queues
+ admin_log
);
sub admin_config {
- my ($vars) = @_;
- my $push = Bugzilla->push_ext;
- my $input = Bugzilla->input_params;
-
- if ($input->{save}) {
- my $token = $input->{token};
- check_hash_token($token, ['push_config']);
- my $dbh = Bugzilla->dbh;
- $dbh->bz_start_transaction();
- _update_config_from_form('global', $push->config);
- foreach my $connector ($push->connectors->list) {
- _update_config_from_form($connector->name, $connector->config);
- }
- $push->set_config_last_modified();
- $dbh->bz_commit_transaction();
- $vars->{message} = 'push_config_updated';
+ my ($vars) = @_;
+ my $push = Bugzilla->push_ext;
+ my $input = Bugzilla->input_params;
+
+ if ($input->{save}) {
+ my $token = $input->{token};
+ check_hash_token($token, ['push_config']);
+ my $dbh = Bugzilla->dbh;
+ $dbh->bz_start_transaction();
+ _update_config_from_form('global', $push->config);
+ foreach my $connector ($push->connectors->list) {
+ _update_config_from_form($connector->name, $connector->config);
}
+ $push->set_config_last_modified();
+ $dbh->bz_commit_transaction();
+ $vars->{message} = 'push_config_updated';
+ }
- $vars->{push} = $push;
- $vars->{connectors} = $push->connectors;
+ $vars->{push} = $push;
+ $vars->{connectors} = $push->connectors;
}
sub _update_config_from_form {
- my ($name, $config) = @_;
- my $input = Bugzilla->input_params;
-
- # read values from form
- my $values = {};
- foreach my $option ($config->options) {
- my $option_name = $option->{name};
- $values->{$option_name} = trim($input->{$name . ".$option_name"});
+ my ($name, $config) = @_;
+ my $input = Bugzilla->input_params;
+
+ # read values from form
+ my $values = {};
+ foreach my $option ($config->options) {
+ my $option_name = $option->{name};
+ $values->{$option_name} = trim($input->{$name . ".$option_name"});
+ }
+
+ # validate
+ if ($values->{enabled} eq 'Enabled') {
+ eval { $config->validate($values); };
+ if ($@) {
+ ThrowUserError('push_error', {error_message => clean_error($@)});
}
+ }
+
+ # update
+ foreach my $option ($config->options) {
+ my $option_name = $option->{name};
+ trick_taint($values->{$option_name});
+ $config->{$option_name} = $values->{$option_name};
+ }
+ $config->update();
+}
- # validate
- if ($values->{enabled} eq 'Enabled') {
- eval {
- $config->validate($values);
- };
- if ($@) {
- ThrowUserError('push_error', { error_message => clean_error($@) });
- }
- }
+sub admin_queues {
+ my ($vars, $page) = @_;
+ my $push = Bugzilla->push_ext;
+ my $input = Bugzilla->input_params;
- # update
- foreach my $option ($config->options) {
- my $option_name = $option->{name};
- trick_taint($values->{$option_name});
- $config->{$option_name} = $values->{$option_name};
+ if ($page eq 'push_queues.html') {
+ $vars->{push} = $push;
+
+ }
+ elsif ($page eq 'push_queues_view.html') {
+ my $queue;
+ if ($input->{connector}) {
+ my $connector = $push->connectors->by_name($input->{connector})
+ || ThrowUserError('push_error', {error_message => 'Invalid connector'});
+ $queue = $connector->backlog;
}
- $config->update();
-}
+ else {
+ $queue = $push->queue;
+ }
+ $vars->{queue} = $queue;
-sub admin_queues {
- my ($vars, $page) = @_;
- my $push = Bugzilla->push_ext;
- my $input = Bugzilla->input_params;
-
- if ($page eq 'push_queues.html') {
- $vars->{push} = $push;
-
- } elsif ($page eq 'push_queues_view.html') {
- my $queue;
- if ($input->{connector}) {
- my $connector = $push->connectors->by_name($input->{connector})
- || ThrowUserError('push_error', { error_message => 'Invalid connector' });
- $queue = $connector->backlog;
- } else {
- $queue = $push->queue;
- }
- $vars->{queue} = $queue;
-
- my $id = $input->{message} || 0;
- detaint_natural($id)
- || ThrowUserError('push_error', { error_message => 'Invalid message ID' });
- my $message = $queue->by_id($id)
- || ThrowUserError('push_error', { error_message => 'Invalid message ID' });
-
- if ($input->{delete}) {
- my $token = $input->{token};
- check_hash_token($token, ['deleteMessage']);
- $message->remove_from_db();
- $vars->{message} = 'push_message_deleted';
-
- } else {
- $vars->{message_obj} = $message;
- eval {
- $vars->{json} = to_json($message->payload_decoded, 1);
- };
- }
+ my $id = $input->{message} || 0;
+ detaint_natural($id)
+ || ThrowUserError('push_error', {error_message => 'Invalid message ID'});
+ my $message = $queue->by_id($id)
+ || ThrowUserError('push_error', {error_message => 'Invalid message ID'});
+
+ if ($input->{delete}) {
+ my $token = $input->{token};
+ check_hash_token($token, ['deleteMessage']);
+ $message->remove_from_db();
+ $vars->{message} = 'push_message_deleted';
+
+ }
+ else {
+ $vars->{message_obj} = $message;
+ eval { $vars->{json} = to_json($message->payload_decoded, 1); };
}
+ }
}
sub admin_log {
- my ($vars) = @_;
- my $push = Bugzilla->push_ext;
- my $input = Bugzilla->input_params;
+ my ($vars) = @_;
+ my $push = Bugzilla->push_ext;
+ my $input = Bugzilla->input_params;
- $vars->{push} = $push;
+ $vars->{push} = $push;
}
1;
diff --git a/extensions/Push/lib/BacklogMessage.pm b/extensions/Push/lib/BacklogMessage.pm
index 28b17bae3..942eb77eb 100644
--- a/extensions/Push/lib/BacklogMessage.pm
+++ b/extensions/Push/lib/BacklogMessage.pm
@@ -28,31 +28,31 @@ use Encode;
# initialisation
#
-use constant DB_TABLE => 'push_backlog';
+use constant DB_TABLE => 'push_backlog';
use constant DB_COLUMNS => qw(
- id
- message_id
- push_ts
- payload
- change_set
- routing_key
- connector
- attempt_ts
- attempts
- last_error
+ id
+ message_id
+ push_ts
+ payload
+ change_set
+ routing_key
+ connector
+ attempt_ts
+ attempts
+ last_error
);
use constant UPDATE_COLUMNS => qw(
- attempt_ts
- attempts
- last_error
+ attempt_ts
+ attempts
+ last_error
);
use constant LIST_ORDER => 'push_ts';
use constant VALIDATORS => {
- payload => \&_check_payload,
- change_set => \&_check_change_set,
- routing_key => \&_check_routing_key,
- connector => \&_check_connector,
- attempts => \&_check_attempts,
+ payload => \&_check_payload,
+ change_set => \&_check_change_set,
+ routing_key => \&_check_routing_key,
+ connector => \&_check_connector,
+ attempts => \&_check_attempts,
};
#
@@ -60,46 +60,46 @@ use constant VALIDATORS => {
#
sub create_from_message {
- my ($class, $message, $connector) = @_;
- my $self = $class->create({
- message_id => $message->id,
- push_ts => $message->push_ts,
- payload => $message->payload,
- change_set => $message->change_set,
- routing_key => $message->routing_key,
- connector => $connector->name,
- attempt_ts => undef,
- attempts => 0,
- last_error => undef,
- });
- return $self;
+ my ($class, $message, $connector) = @_;
+ my $self = $class->create({
+ message_id => $message->id,
+ push_ts => $message->push_ts,
+ payload => $message->payload,
+ change_set => $message->change_set,
+ routing_key => $message->routing_key,
+ connector => $connector->name,
+ attempt_ts => undef,
+ attempts => 0,
+ last_error => undef,
+ });
+ return $self;
}
#
# accessors
#
-sub message_id { return $_[0]->{'message_id'} }
-sub push_ts { return $_[0]->{'push_ts'}; }
-sub payload { return $_[0]->{'payload'}; }
-sub change_set { return $_[0]->{'change_set'}; }
+sub message_id { return $_[0]->{'message_id'} }
+sub push_ts { return $_[0]->{'push_ts'}; }
+sub payload { return $_[0]->{'payload'}; }
+sub change_set { return $_[0]->{'change_set'}; }
sub routing_key { return $_[0]->{'routing_key'}; }
-sub connector { return $_[0]->{'connector'}; }
-sub attempt_ts { return $_[0]->{'attempt_ts'}; }
-sub attempts { return $_[0]->{'attempts'}; }
-sub last_error { return $_[0]->{'last_error'}; }
+sub connector { return $_[0]->{'connector'}; }
+sub attempt_ts { return $_[0]->{'attempt_ts'}; }
+sub attempts { return $_[0]->{'attempts'}; }
+sub last_error { return $_[0]->{'last_error'}; }
sub payload_decoded {
- my ($self) = @_;
- return from_json($self->{'payload'});
+ my ($self) = @_;
+ return from_json($self->{'payload'});
}
sub attempt_time {
- my ($self) = @_;
- if (!exists $self->{'attempt_time'}) {
- $self->{'attempt_time'} = datetime_from($self->attempt_ts)->epoch;
- }
- return $self->{'attempt_time'};
+ my ($self) = @_;
+ if (!exists $self->{'attempt_time'}) {
+ $self->{'attempt_time'} = datetime_from($self->attempt_ts)->epoch;
+ }
+ return $self->{'attempt_time'};
}
#
@@ -107,11 +107,11 @@ sub attempt_time {
#
sub inc_attempts {
- my ($self, $error) = @_;
- $self->{attempt_ts} = Bugzilla->dbh->selectrow_array('SELECT NOW()');
- $self->{attempts} = $self->{attempts} + 1;
- $self->{last_error} = $error;
- $self->update;
+ my ($self, $error) = @_;
+ $self->{attempt_ts} = Bugzilla->dbh->selectrow_array('SELECT NOW()');
+ $self->{attempts} = $self->{attempts} + 1;
+ $self->{last_error} = $error;
+ $self->update;
}
#
@@ -119,32 +119,35 @@ sub inc_attempts {
#
sub _check_payload {
- my ($invocant, $value) = @_;
- length($value) || ThrowCodeError('push_invalid_payload');
- return $value;
+ my ($invocant, $value) = @_;
+ length($value) || ThrowCodeError('push_invalid_payload');
+ return $value;
}
sub _check_change_set {
- my ($invocant, $value) = @_;
- (defined($value) && length($value)) || ThrowCodeError('push_invalid_change_set');
- return $value;
+ my ($invocant, $value) = @_;
+ (defined($value) && length($value))
+ || ThrowCodeError('push_invalid_change_set');
+ return $value;
}
sub _check_routing_key {
- my ($invocant, $value) = @_;
- (defined($value) && length($value)) || ThrowCodeError('push_invalid_routing_key');
- return $value;
+ my ($invocant, $value) = @_;
+ (defined($value) && length($value))
+ || ThrowCodeError('push_invalid_routing_key');
+ return $value;
}
sub _check_connector {
- my ($invocant, $value) = @_;
- Bugzilla->push_ext->connectors->exists($value) || ThrowCodeError('push_invalid_connector');
- return $value;
+ my ($invocant, $value) = @_;
+ Bugzilla->push_ext->connectors->exists($value)
+ || ThrowCodeError('push_invalid_connector');
+ return $value;
}
sub _check_attempts {
- my ($invocant, $value) = @_;
- return $value || 0;
+ my ($invocant, $value) = @_;
+ return $value || 0;
}
1;
diff --git a/extensions/Push/lib/BacklogQueue.pm b/extensions/Push/lib/BacklogQueue.pm
index a7200c688..17d0a188f 100644
--- a/extensions/Push/lib/BacklogQueue.pm
+++ b/extensions/Push/lib/BacklogQueue.pm
@@ -15,74 +15,67 @@ use Bugzilla;
use Bugzilla::Extension::Push::BacklogMessage;
sub new {
- my ($class, $connector) = @_;
- my $self = {};
- bless($self, $class);
- $self->{connector} = $connector;
- return $self;
+ my ($class, $connector) = @_;
+ my $self = {};
+ bless($self, $class);
+ $self->{connector} = $connector;
+ return $self;
}
sub count {
- my ($self) = @_;
- my $dbh = Bugzilla->dbh;
- return $dbh->selectrow_array("
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+ return $dbh->selectrow_array("
SELECT COUNT(*)
FROM push_backlog
- WHERE connector = ?",
- undef,
- $self->{connector});
+ WHERE connector = ?", undef, $self->{connector});
}
sub oldest {
- my ($self) = @_;
- my @messages = $self->list(
- limit => 1,
- filter => 'AND ((next_attempt_ts IS NULL) OR (next_attempt_ts <= NOW()))',
- );
- return scalar(@messages) ? $messages[0] : undef;
+ my ($self) = @_;
+ my @messages = $self->list(
+ limit => 1,
+ filter => 'AND ((next_attempt_ts IS NULL) OR (next_attempt_ts <= NOW()))',
+ );
+ return scalar(@messages) ? $messages[0] : undef;
}
sub by_id {
- my ($self, $id) = @_;
- my @messages = $self->list(
- limit => 1,
- filter => "AND (log.id = $id)",
- );
- return scalar(@messages) ? $messages[0] : undef;
+ my ($self, $id) = @_;
+ my @messages = $self->list(limit => 1, filter => "AND (log.id = $id)",);
+ return scalar(@messages) ? $messages[0] : undef;
}
sub list {
- my ($self, %args) = @_;
- $args{limit} ||= 10;
- $args{filter} ||= '';
- my @result;
- my $dbh = Bugzilla->dbh;
+ my ($self, %args) = @_;
+ $args{limit} ||= 10;
+ $args{filter} ||= '';
+ my @result;
+ my $dbh = Bugzilla->dbh;
- my $filter_sql = $args{filter} || '';
- my $sth = $dbh->prepare("
+ my $filter_sql = $args{filter} || '';
+ my $sth = $dbh->prepare("
SELECT log.id, message_id, push_ts, payload, change_set, routing_key, attempt_ts, log.attempts
FROM push_backlog log
LEFT JOIN push_backoff off ON off.connector = log.connector
- WHERE log.connector = ? ".
- $args{filter} . "
- ORDER BY push_ts " .
- $dbh->sql_limit($args{limit})
- );
- $sth->execute($self->{connector});
- while (my $row = $sth->fetchrow_hashref()) {
- push @result, Bugzilla::Extension::Push::BacklogMessage->new({
- id => $row->{id},
- message_id => $row->{message_id},
- push_ts => $row->{push_ts},
- payload => $row->{payload},
- change_set => $row->{change_set},
- routing_key => $row->{routing_key},
- connector => $self->{connector},
- attempt_ts => $row->{attempt_ts},
- attempts => $row->{attempts},
- });
- }
- return @result;
+ WHERE log.connector = ? " . $args{filter} . "
+ ORDER BY push_ts " . $dbh->sql_limit($args{limit}));
+ $sth->execute($self->{connector});
+ while (my $row = $sth->fetchrow_hashref()) {
+ push @result,
+ Bugzilla::Extension::Push::BacklogMessage->new({
+ id => $row->{id},
+ message_id => $row->{message_id},
+ push_ts => $row->{push_ts},
+ payload => $row->{payload},
+ change_set => $row->{change_set},
+ routing_key => $row->{routing_key},
+ connector => $self->{connector},
+ attempt_ts => $row->{attempt_ts},
+ attempts => $row->{attempts},
+ });
+ }
+ return @result;
}
#
@@ -90,39 +83,40 @@ sub list {
#
sub backoff {
- my ($self) = @_;
- if (!$self->{backoff}) {
- my $ra = Bugzilla::Extension::Push::Backoff->match({
- connector => $self->{connector}
+ my ($self) = @_;
+ if (!$self->{backoff}) {
+ my $ra
+ = Bugzilla::Extension::Push::Backoff->match({connector => $self->{connector}
+ });
+ if (@$ra) {
+ $self->{backoff} = $ra->[0];
+ }
+ else {
+ $self->{backoff}
+ = Bugzilla::Extension::Push::Backoff->create({connector => $self->{connector}
});
- if (@$ra) {
- $self->{backoff} = $ra->[0];
- } else {
- $self->{backoff} = Bugzilla::Extension::Push::Backoff->create({
- connector => $self->{connector}
- });
- }
}
- return $self->{backoff};
+ }
+ return $self->{backoff};
}
sub reset_backoff {
- my ($self) = @_;
- my $backoff = $self->backoff;
- $backoff->reset();
- $backoff->update();
+ my ($self) = @_;
+ my $backoff = $self->backoff;
+ $backoff->reset();
+ $backoff->update();
}
sub inc_backoff {
- my ($self) = @_;
- my $backoff = $self->backoff;
- $backoff->inc();
- $backoff->update();
+ my ($self) = @_;
+ my $backoff = $self->backoff;
+ $backoff->inc();
+ $backoff->update();
}
sub connector {
- my ($self) = @_;
- return $self->{connector};
+ my ($self) = @_;
+ return $self->{connector};
}
1;
diff --git a/extensions/Push/lib/Backoff.pm b/extensions/Push/lib/Backoff.pm
index 0436cdf14..070adfc29 100644
--- a/extensions/Push/lib/Backoff.pm
+++ b/extensions/Push/lib/Backoff.pm
@@ -26,21 +26,21 @@ use Bugzilla::Util;
# initialisation
#
-use constant DB_TABLE => 'push_backoff';
+use constant DB_TABLE => 'push_backoff';
use constant DB_COLUMNS => qw(
- id
- connector
- next_attempt_ts
- attempts
+ id
+ connector
+ next_attempt_ts
+ attempts
);
use constant UPDATE_COLUMNS => qw(
- next_attempt_ts
- attempts
+ next_attempt_ts
+ attempts
);
use constant VALIDATORS => {
- connector => \&_check_connector,
- next_attempt_ts => \&_check_next_attempt_ts,
- attempts => \&_check_attempts,
+ connector => \&_check_connector,
+ next_attempt_ts => \&_check_next_attempt_ts,
+ attempts => \&_check_attempts,
};
use constant LIST_ORDER => 'next_attempt_ts';
@@ -48,16 +48,16 @@ use constant LIST_ORDER => 'next_attempt_ts';
# accessors
#
-sub connector { return $_[0]->{'connector'}; }
+sub connector { return $_[0]->{'connector'}; }
sub next_attempt_ts { return $_[0]->{'next_attempt_ts'}; }
-sub attempts { return $_[0]->{'attempts'}; }
+sub attempts { return $_[0]->{'attempts'}; }
sub next_attempt_time {
- my ($self) = @_;
- if (!exists $self->{'next_attempt_time'}) {
- $self->{'next_attempt_time'} = datetime_from($self->next_attempt_ts)->epoch;
- }
- return $self->{'next_attempt_time'};
+ my ($self) = @_;
+ if (!exists $self->{'next_attempt_time'}) {
+ $self->{'next_attempt_time'} = datetime_from($self->next_attempt_ts)->epoch;
+ }
+ return $self->{'next_attempt_time'};
}
#
@@ -65,25 +65,26 @@ sub next_attempt_time {
#
sub reset {
- my ($self) = @_;
- $self->{next_attempt_ts} = Bugzilla->dbh->selectrow_array('SELECT NOW()');
- $self->{attempts} = 0;
- INFO( sprintf 'resetting backoff for %s', $self->connector );
+ my ($self) = @_;
+ $self->{next_attempt_ts} = Bugzilla->dbh->selectrow_array('SELECT NOW()');
+ $self->{attempts} = 0;
+ INFO(sprintf 'resetting backoff for %s', $self->connector);
}
sub inc {
- my ($self) = @_;
- my $dbh = Bugzilla->dbh;
-
- my $attempts = $self->attempts + 1;
- my $seconds = $attempts <= 4 ? 5 ** $attempts : 15 * 60;
- my ($date) = $dbh->selectrow_array("SELECT " . $dbh->sql_date_math('NOW()', '+', $seconds, 'SECOND'));
-
- $self->{next_attempt_ts} = $date;
- $self->{attempts} = $attempts;
- INFO(
- sprintf 'setting next attempt for %s to %s (attempt %s)', $self->connector, $date, $attempts
- );
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+
+ my $attempts = $self->attempts + 1;
+ my $seconds = $attempts <= 4 ? 5**$attempts : 15 * 60;
+ my ($date)
+ = $dbh->selectrow_array(
+ "SELECT " . $dbh->sql_date_math('NOW()', '+', $seconds, 'SECOND'));
+
+ $self->{next_attempt_ts} = $date;
+ $self->{attempts} = $attempts;
+ INFO(sprintf 'setting next attempt for %s to %s (attempt %s)',
+ $self->connector, $date, $attempts);
}
#
@@ -91,19 +92,20 @@ sub inc {
#
sub _check_connector {
- my ($invocant, $value) = @_;
- Bugzilla->push_ext->connectors->exists($value) || ThrowCodeError('push_invalid_connector');
- return $value;
+ my ($invocant, $value) = @_;
+ Bugzilla->push_ext->connectors->exists($value)
+ || ThrowCodeError('push_invalid_connector');
+ return $value;
}
sub _check_next_attempt_ts {
- my ($invocant, $value) = @_;
- return $value || Bugzilla->dbh->selectrow_array('SELECT NOW()');
+ my ($invocant, $value) = @_;
+ return $value || Bugzilla->dbh->selectrow_array('SELECT NOW()');
}
sub _check_attempts {
- my ($invocant, $value) = @_;
- return $value || 0;
+ my ($invocant, $value) = @_;
+ return $value || 0;
}
1;
diff --git a/extensions/Push/lib/Config.pm b/extensions/Push/lib/Config.pm
index 2db95b972..bb0d523ad 100644
--- a/extensions/Push/lib/Config.pm
+++ b/extensions/Push/lib/Config.pm
@@ -17,199 +17,201 @@ use Bugzilla::Extension::Push::Option;
use Crypt::CBC;
sub new {
- my ($class, $name, @options) = @_;
- my $self = {
- _name => $name
- };
- bless($self, $class);
-
- $self->{_options} = [@options];
- unshift @{$self->{_options}}, {
- name => 'enabled',
- label => 'Status',
- help => '',
- type => 'select',
- values => [ 'Enabled', 'Disabled' ],
- default => 'Disabled',
+ my ($class, $name, @options) = @_;
+ my $self = {_name => $name};
+ bless($self, $class);
+
+ $self->{_options} = [@options];
+ unshift @{$self->{_options}},
+ {
+ name => 'enabled',
+ label => 'Status',
+ help => '',
+ type => 'select',
+ values => ['Enabled', 'Disabled'],
+ default => 'Disabled',
};
- return $self;
+ return $self;
}
sub options {
- my ($self) = @_;
- return @{$self->{_options}};
+ my ($self) = @_;
+ return @{$self->{_options}};
}
sub option {
- my ($self, $name) = @_;
- foreach my $option ($self->options) {
- return $option if $option->{name} eq $name;
- }
- return undef;
+ my ($self, $name) = @_;
+ foreach my $option ($self->options) {
+ return $option if $option->{name} eq $name;
+ }
+ return undef;
}
sub load {
- my ($self) = @_;
- my $config = {};
-
- # prime $config with defaults
- foreach my $rh ($self->options) {
- $config->{$rh->{name}} = $rh->{default};
+ my ($self) = @_;
+ my $config = {};
+
+ # prime $config with defaults
+ foreach my $rh ($self->options) {
+ $config->{$rh->{name}} = $rh->{default};
+ }
+
+ # override defaults with values from database
+ my $options
+ = Bugzilla::Extension::Push::Option->match({connector => $self->{_name},});
+ foreach my $option (@$options) {
+ my $option_config = $self->option($option->name) || next;
+ if ($option_config->{type} eq 'password') {
+ $config->{$option->name} = $self->_decrypt($option->value);
}
-
- # override defaults with values from database
- my $options = Bugzilla::Extension::Push::Option->match({
- connector => $self->{_name},
- });
- foreach my $option (@$options) {
- my $option_config = $self->option($option->name)
- || next;
- if ($option_config->{type} eq 'password') {
- $config->{$option->name} = $self->_decrypt($option->value);
- } else {
- $config->{$option->name} = $option->value;
- }
+ else {
+ $config->{$option->name} = $option->value;
}
+ }
- # validate when running from the daemon
- if (Bugzilla->push_ext->is_daemon) {
- $self->_validate_config($config);
- }
-
- # done, update self
- foreach my $name (keys %$config) {
- my $value = $self->option($name)->{type} eq 'password' ? '********' : $config->{$name};
- TRACE( sprintf "%s: set %s=%s\n", $self->{_name}, $name, $value || '' );
- $self->{$name} = $config->{$name};
- }
+ # validate when running from the daemon
+ if (Bugzilla->push_ext->is_daemon) {
+ $self->_validate_config($config);
+ }
+
+ # done, update self
+ foreach my $name (keys %$config) {
+ my $value
+ = $self->option($name)->{type} eq 'password' ? '********' : $config->{$name};
+ TRACE(sprintf "%s: set %s=%s\n", $self->{_name}, $name, $value || '');
+ $self->{$name} = $config->{$name};
+ }
}
sub validate {
- my ($self, $config) = @_;
- $self->_validate_mandatory($config);
- $self->_validate_config($config);
+ my ($self, $config) = @_;
+ $self->_validate_mandatory($config);
+ $self->_validate_config($config);
}
sub update {
- my ($self) = @_;
-
- my @valid_options = map { $_->{name} } $self->options;
-
- my %options;
- my $options_list = Bugzilla::Extension::Push::Option->match({
- connector => $self->{_name},
- });
- foreach my $option (@$options_list) {
- $options{$option->name} = $option;
- }
-
- # delete options which are no longer valid
- foreach my $name (keys %options) {
- if (!grep { $_ eq $name } @valid_options) {
- $options{$name}->remove_from_db();
- delete $options{$name};
- }
+ my ($self) = @_;
+
+ my @valid_options = map { $_->{name} } $self->options;
+
+ my %options;
+ my $options_list
+ = Bugzilla::Extension::Push::Option->match({connector => $self->{_name},});
+ foreach my $option (@$options_list) {
+ $options{$option->name} = $option;
+ }
+
+ # delete options which are no longer valid
+ foreach my $name (keys %options) {
+ if (!grep { $_ eq $name } @valid_options) {
+ $options{$name}->remove_from_db();
+ delete $options{$name};
}
+ }
- # update options
- foreach my $name (keys %options) {
- my $option = $options{$name};
- if ($self->option($name)->{type} eq 'password') {
- $option->set_value($self->_encrypt($self->{$name}));
- } else {
- $option->set_value($self->{$name});
- }
- $option->update();
+ # update options
+ foreach my $name (keys %options) {
+ my $option = $options{$name};
+ if ($self->option($name)->{type} eq 'password') {
+ $option->set_value($self->_encrypt($self->{$name}));
}
-
- # add missing options
- foreach my $name (@valid_options) {
- next if exists $options{$name};
- Bugzilla::Extension::Push::Option->create({
- connector => $self->{_name},
- option_name => $name,
- option_value => $self->{$name},
- });
+ else {
+ $option->set_value($self->{$name});
}
+ $option->update();
+ }
+
+ # add missing options
+ foreach my $name (@valid_options) {
+ next if exists $options{$name};
+ Bugzilla::Extension::Push::Option->create({
+ connector => $self->{_name},
+ option_name => $name,
+ option_value => $self->{$name},
+ });
+ }
}
sub _remove_invalid_options {
- my ($self, $config) = @_;
- my @names;
- foreach my $rh ($self->options) {
- push @names, $rh->{name};
- }
- foreach my $name (keys %$config) {
- if ($name =~ /^_/ || !grep { $_ eq $name } @names) {
- delete $config->{$name};
- }
+ my ($self, $config) = @_;
+ my @names;
+ foreach my $rh ($self->options) {
+ push @names, $rh->{name};
+ }
+ foreach my $name (keys %$config) {
+ if ($name =~ /^_/ || !grep { $_ eq $name } @names) {
+ delete $config->{$name};
}
+ }
}
sub _validate_mandatory {
- my ($self, $config) = @_;
- $self->_remove_invalid_options($config);
-
- my @missing;
- foreach my $option ($self->options) {
- next unless $option->{required};
- my $name = $option->{name};
- if (!exists $config->{$name} || !defined($config->{$name}) || $config->{$name} eq '') {
- push @missing, $option;
- }
+ my ($self, $config) = @_;
+ $self->_remove_invalid_options($config);
+
+ my @missing;
+ foreach my $option ($self->options) {
+ next unless $option->{required};
+ my $name = $option->{name};
+ if ( !exists $config->{$name}
+ || !defined($config->{$name})
+ || $config->{$name} eq '')
+ {
+ push @missing, $option;
+ }
+ }
+ if (@missing) {
+ my $connector = $self->{_name};
+ @missing = map { $_->{label} } @missing;
+ if (scalar @missing == 1) {
+ die "The option '$missing[0]' for the connector '$connector' is mandatory\n";
}
- if (@missing) {
- my $connector = $self->{_name};
- @missing = map { $_->{label} } @missing;
- if (scalar @missing == 1) {
- die "The option '$missing[0]' for the connector '$connector' is mandatory\n";
- } else {
- die "The following options for the connector '$connector' are mandatory:\n "
- . join("\n ", @missing) . "\n";
- }
+ else {
+ die "The following options for the connector '$connector' are mandatory:\n "
+ . join("\n ", @missing) . "\n";
}
+ }
}
sub _validate_config {
- my ($self, $config) = @_;
- $self->_remove_invalid_options($config);
-
- my @errors;
- foreach my $option ($self->options) {
- my $name = $option->{name};
- next unless exists $config->{$name} && exists $option->{validate};
- eval {
- $option->{validate}->($config->{$name}, $config);
- };
- push @errors, $@ if $@;
- }
- die join("\n", @errors) if @errors;
-
- if ($self->{_name} ne 'global') {
- my $class = 'Bugzilla::Extension::Push::Connector::' . $self->{_name};
- $class->options_validate($config);
- }
+ my ($self, $config) = @_;
+ $self->_remove_invalid_options($config);
+
+ my @errors;
+ foreach my $option ($self->options) {
+ my $name = $option->{name};
+ next unless exists $config->{$name} && exists $option->{validate};
+ eval { $option->{validate}->($config->{$name}, $config); };
+ push @errors, $@ if $@;
+ }
+ die join("\n", @errors) if @errors;
+
+ if ($self->{_name} ne 'global') {
+ my $class = 'Bugzilla::Extension::Push::Connector::' . $self->{_name};
+ $class->options_validate($config);
+ }
}
sub _cipher {
- my ($self) = @_;
- $self->{_cipher} ||= Crypt::CBC->new(
- -key => Bugzilla->localconfig->{'site_wide_secret'},
- -cipher => 'DES_EDE3');
- return $self->{_cipher};
+ my ($self) = @_;
+ $self->{_cipher} ||= Crypt::CBC->new(
+ -key => Bugzilla->localconfig->{'site_wide_secret'},
+ -cipher => 'DES_EDE3'
+ );
+ return $self->{_cipher};
}
sub _decrypt {
- my ($self, $value) = @_;
- my $result;
- eval { $result = $self->_cipher->decrypt_hex($value) };
- return $@ ? '' : $result;
+ my ($self, $value) = @_;
+ my $result;
+ eval { $result = $self->_cipher->decrypt_hex($value) };
+ return $@ ? '' : $result;
}
sub _encrypt {
- my ($self, $value) = @_;
- return $self->_cipher->encrypt_hex($value);
+ my ($self, $value) = @_;
+ return $self->_cipher->encrypt_hex($value);
}
1;
diff --git a/extensions/Push/lib/Connector.disabled/AMQP.pm b/extensions/Push/lib/Connector.disabled/AMQP.pm
index 1ba365e21..dda73dade 100644
--- a/extensions/Push/lib/Connector.disabled/AMQP.pm
+++ b/extensions/Push/lib/Connector.disabled/AMQP.pm
@@ -20,211 +20,197 @@ use Bugzilla::Util qw(generate_random_password);
use DateTime;
sub init {
- my ($self) = @_;
- $self->{mq} = 0;
- $self->{channel} = 1;
-
- if ($self->config->{queue}) {
- $self->{queue_name} = $self->config->{queue};
- } else {
- my $queue_name = Bugzilla->localconfig->{'urlbase'};
- $queue_name =~ s#^https?://##;
- $queue_name =~ s#/$#|#;
- $queue_name .= generate_random_password(16);
- $self->{queue_name} = $queue_name;
- }
+ my ($self) = @_;
+ $self->{mq} = 0;
+ $self->{channel} = 1;
+
+ if ($self->config->{queue}) {
+ $self->{queue_name} = $self->config->{queue};
+ }
+ else {
+ my $queue_name = Bugzilla->localconfig->{'urlbase'};
+ $queue_name =~ s#^https?://##;
+ $queue_name =~ s#/$#|#;
+ $queue_name .= generate_random_password(16);
+ $self->{queue_name} = $queue_name;
+ }
}
sub options {
- return (
- {
- name => 'host',
- label => 'AMQP Hostname',
- type => 'string',
- default => 'localhost',
- required => 1,
- },
- {
- name => 'port',
- label => 'AMQP Port',
- type => 'string',
- default => '5672',
- required => 1,
- validate => sub {
- $_[0] =~ /\D/ && die "Invalid port (must be numeric)\n";
- },
- },
- {
- name => 'username',
- label => 'Username',
- type => 'string',
- default => 'guest',
- required => 1,
- },
- {
- name => 'password',
- label => 'Password',
- type => 'password',
- default => 'guest',
- required => 1,
- },
- {
- name => 'vhost',
- label => 'Virtual Host',
- type => 'string',
- default => '/',
- required => 1,
- },
- {
- name => 'exchange',
- label => 'Exchange',
- type => 'string',
- default => '',
- required => 1,
- },
- {
- name => 'queue',
- label => 'Queue',
- type => 'string',
- },
- );
+ return (
+ {
+ name => 'host',
+ label => 'AMQP Hostname',
+ type => 'string',
+ default => 'localhost',
+ required => 1,
+ },
+ {
+ name => 'port',
+ label => 'AMQP Port',
+ type => 'string',
+ default => '5672',
+ required => 1,
+ validate => sub {
+ $_[0] =~ /\D/ && die "Invalid port (must be numeric)\n";
+ },
+ },
+ {
+ name => 'username',
+ label => 'Username',
+ type => 'string',
+ default => 'guest',
+ required => 1,
+ },
+ {
+ name => 'password',
+ label => 'Password',
+ type => 'password',
+ default => 'guest',
+ required => 1,
+ },
+ {
+ name => 'vhost',
+ label => 'Virtual Host',
+ type => 'string',
+ default => '/',
+ required => 1,
+ },
+ {
+ name => 'exchange',
+ label => 'Exchange',
+ type => 'string',
+ default => '',
+ required => 1,
+ },
+ {name => 'queue', label => 'Queue', type => 'string',},
+ );
}
sub stop {
- my ($self) = @_;
- if ($self->{mq}) {
- Bugzilla->push_ext->logger->debug('AMQP: disconnecting');
- $self->{mq}->disconnect();
- $self->{mq} = 0;
- }
+ my ($self) = @_;
+ if ($self->{mq}) {
+ Bugzilla->push_ext->logger->debug('AMQP: disconnecting');
+ $self->{mq}->disconnect();
+ $self->{mq} = 0;
+ }
}
sub _connect {
- my ($self) = @_;
- my $logger = Bugzilla->push_ext->logger;
- my $config = $self->config;
-
- $self->stop();
-
- $logger->debug('AMQP: Connecting to RabbitMQ ' . $config->{host} . ':' . $config->{port});
- require Net::RabbitMQ;
- my $mq = Net::RabbitMQ->new();
- $mq->connect(
- $config->{host},
- {
- port => $config->{port},
- user => $config->{username},
- password => $config->{password},
- }
- );
- $self->{mq} = $mq;
-
- $logger->debug('AMQP: Opening channel ' . $self->{channel});
- $self->{mq}->channel_open($self->{channel});
-
- $logger->debug('AMQP: Declaring queue ' . $self->{queue_name});
- $self->{mq}->queue_declare(
- $self->{channel},
- $self->{queue_name},
- {
- passive => 0,
- durable => 1,
- exclusive => 0,
- auto_delete => 0,
- },
- );
+ my ($self) = @_;
+ my $logger = Bugzilla->push_ext->logger;
+ my $config = $self->config;
+
+ $self->stop();
+
+ $logger->debug(
+ 'AMQP: Connecting to RabbitMQ ' . $config->{host} . ':' . $config->{port});
+ require Net::RabbitMQ;
+ my $mq = Net::RabbitMQ->new();
+ $mq->connect(
+ $config->{host},
+ {
+ port => $config->{port},
+ user => $config->{username},
+ password => $config->{password},
+ }
+ );
+ $self->{mq} = $mq;
+
+ $logger->debug('AMQP: Opening channel ' . $self->{channel});
+ $self->{mq}->channel_open($self->{channel});
+
+ $logger->debug('AMQP: Declaring queue ' . $self->{queue_name});
+ $self->{mq}->queue_declare($self->{channel}, $self->{queue_name},
+ {passive => 0, durable => 1, exclusive => 0, auto_delete => 0,},
+ );
}
sub _bind {
- my ($self, $message) = @_;
- my $logger = Bugzilla->push_ext->logger;
- my $config = $self->config;
-
- # bind to queue (also acts to verify the connection is still valid)
- if ($self->{mq}) {
- eval {
- $logger->debug('AMQP: binding queue(' . $self->{queue_name} . ') with exchange(' . $config->{exchange} . ')');
- $self->{mq}->queue_bind(
- $self->{channel},
- $self->{queue_name},
- $config->{exchange},
- $message->routing_key,
- );
- };
- if ($@) {
- $logger->debug('AMQP: ' . clean_error($@));
- $self->{mq} = 0;
- }
+ my ($self, $message) = @_;
+ my $logger = Bugzilla->push_ext->logger;
+ my $config = $self->config;
+
+ # bind to queue (also acts to verify the connection is still valid)
+ if ($self->{mq}) {
+ eval {
+ $logger->debug('AMQP: binding queue('
+ . $self->{queue_name}
+ . ') with exchange('
+ . $config->{exchange}
+ . ')');
+ $self->{mq}->queue_bind(
+ $self->{channel}, $self->{queue_name},
+ $config->{exchange}, $message->routing_key,
+ );
+ };
+ if ($@) {
+ $logger->debug('AMQP: ' . clean_error($@));
+ $self->{mq} = 0;
}
+ }
}
sub should_send {
- my ($self, $message) = @_;
- my $logger = Bugzilla->push_ext->logger;
-
- my $payload = $message->payload_decoded();
- my $target = $payload->{event}->{target};
- my $is_private = $payload->{$target}->{is_private} ? 1 : 0;
- if (!$is_private && exists $payload->{$target}->{bug}) {
- $is_private = $payload->{$target}->{bug}->{is_private} ? 1 : 0;
- }
-
- if ($is_private) {
- # we only want to push the is_private message from the change_set, as
- # this is guaranteed to contain public information only
- if ($message->routing_key !~ /\.modify:is_private$/) {
- $logger->debug('AMQP: Ignoring private message');
- return 0;
- }
- $logger->debug('AMQP: Sending change of message to is_private');
+ my ($self, $message) = @_;
+ my $logger = Bugzilla->push_ext->logger;
+
+ my $payload = $message->payload_decoded();
+ my $target = $payload->{event}->{target};
+ my $is_private = $payload->{$target}->{is_private} ? 1 : 0;
+ if (!$is_private && exists $payload->{$target}->{bug}) {
+ $is_private = $payload->{$target}->{bug}->{is_private} ? 1 : 0;
+ }
+
+ if ($is_private) {
+
+ # we only want to push the is_private message from the change_set, as
+ # this is guaranteed to contain public information only
+ if ($message->routing_key !~ /\.modify:is_private$/) {
+ $logger->debug('AMQP: Ignoring private message');
+ return 0;
}
- return 1;
+ $logger->debug('AMQP: Sending change of message to is_private');
+ }
+ return 1;
}
sub send {
- my ($self, $message) = @_;
- my $logger = Bugzilla->push_ext->logger;
- my $config = $self->config;
-
- # don't push comments to pulse
- if ($message->routing_key =~ /^comment\./) {
- $logger->debug('AMQP: Ignoring comment');
- return PUSH_RESULT_IGNORED;
- }
+ my ($self, $message) = @_;
+ my $logger = Bugzilla->push_ext->logger;
+ my $config = $self->config;
- # don't push private data
- $self->should_push($message)
- || return PUSH_RESULT_IGNORED;
+ # don't push comments to pulse
+ if ($message->routing_key =~ /^comment\./) {
+ $logger->debug('AMQP: Ignoring comment');
+ return PUSH_RESULT_IGNORED;
+ }
- $self->_bind($message);
+ # don't push private data
+ $self->should_push($message) || return PUSH_RESULT_IGNORED;
- eval {
- # reconnect if required
- if (!$self->{mq}) {
- $self->_connect();
- }
-
- # send message
- $logger->debug('AMQP: Publishing message');
- $self->{mq}->publish(
- $self->{channel},
- $message->routing_key,
- $message->payload,
- {
- exchange => $config->{exchange},
- },
- {
- content_type => 'text/plain',
- content_encoding => '8bit',
- },
- );
- };
- if ($@) {
- return (PUSH_RESULT_TRANSIENT, clean_error($@));
+ $self->_bind($message);
+
+ eval {
+ # reconnect if required
+ if (!$self->{mq}) {
+ $self->_connect();
}
- return PUSH_RESULT_OK;
+ # send message
+ $logger->debug('AMQP: Publishing message');
+ $self->{mq}->publish(
+ $self->{channel}, $message->routing_key, $message->payload,
+ {exchange => $config->{exchange},},
+ {content_type => 'text/plain', content_encoding => '8bit',},
+ );
+ };
+ if ($@) {
+ return (PUSH_RESULT_TRANSIENT, clean_error($@));
+ }
+
+ return PUSH_RESULT_OK;
}
1;
diff --git a/extensions/Push/lib/Connector.disabled/ServiceNow.pm b/extensions/Push/lib/Connector.disabled/ServiceNow.pm
index d0ebdcf10..032e47dde 100644
--- a/extensions/Push/lib/Connector.disabled/ServiceNow.pm
+++ b/extensions/Push/lib/Connector.disabled/ServiceNow.pm
@@ -32,403 +32,411 @@ use MIME::Base64;
use Net::LDAP;
use constant SEND_COMPONENTS => (
- {
- product => 'mozilla.org',
- component => 'Server Operations: Desktop Issues',
- },
+ {product => 'mozilla.org', component => 'Server Operations: Desktop Issues',},
);
sub options {
- return (
- {
- name => 'bugzilla_user',
- label => 'Bugzilla Service-Now User',
- type => 'string',
- default => 'service.now@bugzilla.tld',
- required => 1,
- validate => sub {
- Bugzilla::User->new({ name => $_[0] })
- || die "Invalid Bugzilla user ($_[0])\n";
- },
- },
- {
- name => 'ldap_scheme',
- label => 'Mozilla LDAP Scheme',
- type => 'select',
- values => [ 'LDAP', 'LDAPS' ],
- default => 'LDAPS',
- required => 1,
- },
- {
- name => 'ldap_host',
- label => 'Mozilla LDAP Host',
- type => 'string',
- default => '',
- required => 1,
- },
- {
- name => 'ldap_user',
- label => 'Mozilla LDAP Bind Username',
- type => 'string',
- default => '',
- required => 1,
- },
- {
- name => 'ldap_pass',
- label => 'Mozilla LDAP Password',
- type => 'password',
- default => '',
- required => 1,
- },
- {
- name => 'ldap_poll',
- label => 'Mozilla LDAP Poll Frequency',
- type => 'string',
- default => '3',
- required => 1,
- help => 'minutes',
- validate => sub {
- $_[0] =~ /\D/
- && die "LDAP Poll Frequency must be an integer\n";
- $_[0] == 0
- && die "LDAP Poll Frequency cannot be less than one minute\n";
- },
- },
- {
- name => 'service_now_url',
- label => 'Service Now JSON URL',
- type => 'string',
- default => 'https://mozilladev.service-now.com',
- required => 1,
- help => "Must start with https:// and end with ?JSON",
- validate => sub {
- $_[0] =~ m#^https://[^\.\/]+\.service-now\.com\/#
- || die "Invalid Service Now JSON URL\n";
- $_[0] =~ m#\?JSON$#
- || die "Invalid Service Now JSON URL (must end with ?JSON)\n";
- },
- },
- {
- name => 'service_now_user',
- label => 'Service Now JSON Username',
- type => 'string',
- default => '',
- required => 1,
- },
- {
- name => 'service_now_pass',
- label => 'Service Now JSON Password',
- type => 'password',
- default => '',
- required => 1,
- },
- );
+ return (
+ {
+ name => 'bugzilla_user',
+ label => 'Bugzilla Service-Now User',
+ type => 'string',
+ default => 'service.now@bugzilla.tld',
+ required => 1,
+ validate => sub {
+ Bugzilla::User->new({name => $_[0]}) || die "Invalid Bugzilla user ($_[0])\n";
+ },
+ },
+ {
+ name => 'ldap_scheme',
+ label => 'Mozilla LDAP Scheme',
+ type => 'select',
+ values => ['LDAP', 'LDAPS'],
+ default => 'LDAPS',
+ required => 1,
+ },
+ {
+ name => 'ldap_host',
+ label => 'Mozilla LDAP Host',
+ type => 'string',
+ default => '',
+ required => 1,
+ },
+ {
+ name => 'ldap_user',
+ label => 'Mozilla LDAP Bind Username',
+ type => 'string',
+ default => '',
+ required => 1,
+ },
+ {
+ name => 'ldap_pass',
+ label => 'Mozilla LDAP Password',
+ type => 'password',
+ default => '',
+ required => 1,
+ },
+ {
+ name => 'ldap_poll',
+ label => 'Mozilla LDAP Poll Frequency',
+ type => 'string',
+ default => '3',
+ required => 1,
+ help => 'minutes',
+ validate => sub {
+ $_[0] =~ /\D/ && die "LDAP Poll Frequency must be an integer\n";
+ $_[0] == 0 && die "LDAP Poll Frequency cannot be less than one minute\n";
+ },
+ },
+ {
+ name => 'service_now_url',
+ label => 'Service Now JSON URL',
+ type => 'string',
+ default => 'https://mozilladev.service-now.com',
+ required => 1,
+ help => "Must start with https:// and end with ?JSON",
+ validate => sub {
+ $_[0] =~ m#^https://[^\.\/]+\.service-now\.com\/#
+ || die "Invalid Service Now JSON URL\n";
+ $_[0] =~ m#\?JSON$#
+ || die "Invalid Service Now JSON URL (must end with ?JSON)\n";
+ },
+ },
+ {
+ name => 'service_now_user',
+ label => 'Service Now JSON Username',
+ type => 'string',
+ default => '',
+ required => 1,
+ },
+ {
+ name => 'service_now_pass',
+ label => 'Service Now JSON Password',
+ type => 'password',
+ default => '',
+ required => 1,
+ },
+ );
}
sub options_validate {
- my ($self, $config) = @_;
- my $host = $config->{ldap_host};
- trick_taint($host);
- my $scheme = lc($config->{ldap_scheme});
- eval {
- my $ldap = Net::LDAP->new($host, scheme => $scheme, onerror => 'die', timeout => 5)
- or die $!;
- $ldap->bind($config->{ldap_user}, password => $config->{ldap_pass});
- };
- if ($@) {
- die sprintf("Failed to connect to %s://%s/: %s\n", $scheme, $host, $@);
- }
+ my ($self, $config) = @_;
+ my $host = $config->{ldap_host};
+ trick_taint($host);
+ my $scheme = lc($config->{ldap_scheme});
+ eval {
+ my $ldap
+ = Net::LDAP->new($host, scheme => $scheme, onerror => 'die', timeout => 5)
+ or die $!;
+ $ldap->bind($config->{ldap_user}, password => $config->{ldap_pass});
+ };
+ if ($@) {
+ die sprintf("Failed to connect to %s://%s/: %s\n", $scheme, $host, $@);
+ }
}
my $_instance;
sub init {
- my ($self) = @_;
- $_instance = $self;
+ my ($self) = @_;
+ $_instance = $self;
}
sub load_config {
- my ($self) = @_;
- $self->SUPER::load_config(@_);
- $self->{bugzilla_user} ||= Bugzilla::User->new({ name => $self->config->{bugzilla_user} });
+ my ($self) = @_;
+ $self->SUPER::load_config(@_);
+ $self->{bugzilla_user}
+ ||= Bugzilla::User->new({name => $self->config->{bugzilla_user}});
}
sub should_send {
- my ($self, $message) = @_;
-
- my $data = $message->payload_decoded;
- my $bug_data = $self->_get_bug_data($data)
- || return 0;
-
- # we don't want to send the initial comment in a separate message
- # because we inject it into the inital message
- if (exists $data->{comment} && $data->{comment}->{number} == 0) {
- return 0;
- }
-
- my $target = $data->{event}->{target};
- unless ($target eq 'bug' || $target eq 'comment' || $target eq 'attachment') {
- return 0;
- }
-
- # ensure the service-now user can see the bug
- if (!$self->{bugzilla_user} || !$self->{bugzilla_user}->is_enabled) {
- return 0;
- }
- $self->{bugzilla_user}->can_see_bug($bug_data->{id})
- || return 0;
-
- # don't push changes made by the service-now account
- $data->{event}->{user}->{id} == $self->{bugzilla_user}->id
- && return 0;
-
- # filter based on the component
- my $bug = Bugzilla::Bug->new($bug_data->{id});
- my $send = 0;
- foreach my $rh (SEND_COMPONENTS) {
- if ($bug->product eq $rh->{product} && $bug->component eq $rh->{component}) {
- $send = 1;
- last;
- }
+ my ($self, $message) = @_;
+
+ my $data = $message->payload_decoded;
+ my $bug_data = $self->_get_bug_data($data) || return 0;
+
+ # we don't want to send the initial comment in a separate message
+ # because we inject it into the inital message
+ if (exists $data->{comment} && $data->{comment}->{number} == 0) {
+ return 0;
+ }
+
+ my $target = $data->{event}->{target};
+ unless ($target eq 'bug' || $target eq 'comment' || $target eq 'attachment') {
+ return 0;
+ }
+
+ # ensure the service-now user can see the bug
+ if (!$self->{bugzilla_user} || !$self->{bugzilla_user}->is_enabled) {
+ return 0;
+ }
+ $self->{bugzilla_user}->can_see_bug($bug_data->{id}) || return 0;
+
+ # don't push changes made by the service-now account
+ $data->{event}->{user}->{id} == $self->{bugzilla_user}->id && return 0;
+
+ # filter based on the component
+ my $bug = Bugzilla::Bug->new($bug_data->{id});
+ my $send = 0;
+ foreach my $rh (SEND_COMPONENTS) {
+ if ($bug->product eq $rh->{product} && $bug->component eq $rh->{component}) {
+ $send = 1;
+ last;
}
- return $send;
+ }
+ return $send;
}
sub send {
- my ($self, $message) = @_;
- my $logger = Bugzilla->push_ext->logger;
- my $config = $self->config;
-
- # should_send intiailises bugzilla_user; make sure we return a useful error message
- if (!$self->{bugzilla_user}) {
- return (PUSH_RESULT_TRANSIENT, "Invalid bugzilla-user (" . $self->config->{bugzilla_user} . ")");
- }
-
- # load the bug
- my $data = $message->payload_decoded;
- my $bug_data = $self->_get_bug_data($data);
- my $bug = Bugzilla::Bug->new($bug_data->{id});
-
- if ($message->routing_key eq 'bug.create') {
- # inject the comment into the data for new bugs
- my $comment = shift @{ $bug->comments };
- if ($comment->body ne '') {
- $bug_data->{comment} = Bugzilla::Extension::Push::Serialise->instance->object_to_hash($comment, 1);
- }
-
- } elsif ($message->routing_key eq 'attachment.create') {
- # inject the attachment payload
- my $attachment = Bugzilla::Attachment->new($data->{attachment}->{id});
- $data->{attachment}->{data} = encode_base64($attachment->data);
- }
-
- # map bmo login to ldap login and insert into json payload
- $self->_add_ldap_logins($data, {});
-
- # flatten json data
- $self->_flatten($data);
-
- # add sysparm_action
- $data->{sysparm_action} = 'insert';
-
- if ($logger->debugging) {
- $logger->debug(to_json(ref($data) ? $data : from_json($data), 1));
- }
-
- # send to service-now
- my $request = HTTP::Request->new(POST => $self->config->{service_now_url});
- $request->content_type('application/json');
- $request->content(to_json($data));
- $request->authorization_basic($self->config->{service_now_user}, $self->config->{service_now_pass});
-
- $self->{lwp} ||= LWP::UserAgent->new(agent => Bugzilla->localconfig->{urlbase});
- my $result = $self->{lwp}->request($request);
-
- # http level errors
- if (!$result->is_success) {
- # treat these as transient
- return (PUSH_RESULT_TRANSIENT, $result->status_line);
- }
-
- # empty response
- if (length($result->content) == 0) {
- # malformed request, treat as transient to allow code to fix
- # may also be misconfiguration on servicenow, also transient
- return (PUSH_RESULT_TRANSIENT, "Empty response");
+ my ($self, $message) = @_;
+ my $logger = Bugzilla->push_ext->logger;
+ my $config = $self->config;
+
+# should_send intiailises bugzilla_user; make sure we return a useful error message
+ if (!$self->{bugzilla_user}) {
+ return (PUSH_RESULT_TRANSIENT,
+ "Invalid bugzilla-user (" . $self->config->{bugzilla_user} . ")");
+ }
+
+ # load the bug
+ my $data = $message->payload_decoded;
+ my $bug_data = $self->_get_bug_data($data);
+ my $bug = Bugzilla::Bug->new($bug_data->{id});
+
+ if ($message->routing_key eq 'bug.create') {
+
+ # inject the comment into the data for new bugs
+ my $comment = shift @{$bug->comments};
+ if ($comment->body ne '') {
+ $bug_data->{comment}
+ = Bugzilla::Extension::Push::Serialise->instance->object_to_hash($comment, 1);
}
- # json errors
- my $result_data;
- eval {
- $result_data = from_json($result->content);
- };
- if ($@) {
- return (PUSH_RESULT_TRANSIENT, clean_error($@));
- }
- if ($logger->debugging) {
- $logger->debug(to_json($result_data, 1));
- }
- if (exists $result_data->{error}) {
- return (PUSH_RESULT_ERROR, $result_data->{error});
- };
-
- # malformed/unexpected json response
- if (!exists $result_data->{records}
- || ref($result_data->{records}) ne 'ARRAY'
- || scalar(@{$result_data->{records}}) == 0
- ) {
- return (PUSH_RESULT_ERROR, "Malformed JSON response from ServiceNow: missing or empty 'records' array");
- }
-
- my $record = $result_data->{records}->[0];
- if (ref($record) ne 'HASH') {
- return (PUSH_RESULT_ERROR, "Malformed JSON response from ServiceNow: 'records' array does not contain an object");
- }
+ }
+ elsif ($message->routing_key eq 'attachment.create') {
+
+ # inject the attachment payload
+ my $attachment = Bugzilla::Attachment->new($data->{attachment}->{id});
+ $data->{attachment}->{data} = encode_base64($attachment->data);
+ }
+
+ # map bmo login to ldap login and insert into json payload
+ $self->_add_ldap_logins($data, {});
+
+ # flatten json data
+ $self->_flatten($data);
+
+ # add sysparm_action
+ $data->{sysparm_action} = 'insert';
+
+ if ($logger->debugging) {
+ $logger->debug(to_json(ref($data) ? $data : from_json($data), 1));
+ }
+
+ # send to service-now
+ my $request = HTTP::Request->new(POST => $self->config->{service_now_url});
+ $request->content_type('application/json');
+ $request->content(to_json($data));
+ $request->authorization_basic($self->config->{service_now_user},
+ $self->config->{service_now_pass});
+
+ $self->{lwp} ||= LWP::UserAgent->new(agent => Bugzilla->localconfig->{urlbase});
+ my $result = $self->{lwp}->request($request);
+
+ # http level errors
+ if (!$result->is_success) {
+
+ # treat these as transient
+ return (PUSH_RESULT_TRANSIENT, $result->status_line);
+ }
+
+ # empty response
+ if (length($result->content) == 0) {
+
+ # malformed request, treat as transient to allow code to fix
+ # may also be misconfiguration on servicenow, also transient
+ return (PUSH_RESULT_TRANSIENT, "Empty response");
+ }
+
+ # json errors
+ my $result_data;
+ eval { $result_data = from_json($result->content); };
+ if ($@) {
+ return (PUSH_RESULT_TRANSIENT, clean_error($@));
+ }
+ if ($logger->debugging) {
+ $logger->debug(to_json($result_data, 1));
+ }
+ if (exists $result_data->{error}) {
+ return (PUSH_RESULT_ERROR, $result_data->{error});
+ }
+
+ # malformed/unexpected json response
+ if (!exists $result_data->{records}
+ || ref($result_data->{records}) ne 'ARRAY'
+ || scalar(@{$result_data->{records}}) == 0)
+ {
+ return (PUSH_RESULT_ERROR,
+ "Malformed JSON response from ServiceNow: missing or empty 'records' array");
+ }
+
+ my $record = $result_data->{records}->[0];
+ if (ref($record) ne 'HASH') {
+ return (PUSH_RESULT_ERROR,
+ "Malformed JSON response from ServiceNow: 'records' array does not contain an object"
+ );
+ }
- # sys_id is the unique identifier for this action
- if (!exists $record->{sys_id} || $record->{sys_id} eq '') {
- return (PUSH_RESULT_ERROR, "Malformed JSON response from ServiceNow: 'records object' does not contain a valid sys_id");
- }
+ # sys_id is the unique identifier for this action
+ if (!exists $record->{sys_id} || $record->{sys_id} eq '') {
+ return (PUSH_RESULT_ERROR,
+ "Malformed JSON response from ServiceNow: 'records object' does not contain a valid sys_id"
+ );
+ }
- # success
- return (PUSH_RESULT_OK, "sys_id: " . $record->{sys_id});
+ # success
+ return (PUSH_RESULT_OK, "sys_id: " . $record->{sys_id});
}
sub _get_bug_data {
- my ($self, $data) = @_;
- my $target = $data->{event}->{target};
- if ($target eq 'bug') {
- return $data->{bug};
- } elsif (exists $data->{$target}->{bug}) {
- return $data->{$target}->{bug};
- } else {
- return;
- }
+ my ($self, $data) = @_;
+ my $target = $data->{event}->{target};
+ if ($target eq 'bug') {
+ return $data->{bug};
+ }
+ elsif (exists $data->{$target}->{bug}) {
+ return $data->{$target}->{bug};
+ }
+ else {
+ return;
+ }
}
sub _flatten {
- # service-now expects a flat json object
- my ($self, $data) = @_;
- my $target = $data->{event}->{target};
+ # service-now expects a flat json object
+ my ($self, $data) = @_;
- # delete unnecessary deep objects
- if ($target eq 'comment' || $target eq 'attachment') {
- $data->{$target}->{bug_id} = $data->{$target}->{bug}->{id};
- delete $data->{$target}->{bug};
- }
- delete $data->{event}->{changes};
+ my $target = $data->{event}->{target};
- $self->_flatten_hash($data, $data, 'u');
+ # delete unnecessary deep objects
+ if ($target eq 'comment' || $target eq 'attachment') {
+ $data->{$target}->{bug_id} = $data->{$target}->{bug}->{id};
+ delete $data->{$target}->{bug};
+ }
+ delete $data->{event}->{changes};
+
+ $self->_flatten_hash($data, $data, 'u');
}
sub _flatten_hash {
- my ($self, $base_hash, $hash, $prefix) = @_;
- foreach my $key (keys %$hash) {
- if (ref($hash->{$key}) eq 'HASH') {
- $self->_flatten_hash($base_hash, $hash->{$key}, $prefix . "_$key");
- } elsif (ref($hash->{$key}) ne 'ARRAY') {
- $base_hash->{$prefix . "_$key"} = $hash->{$key};
- }
- delete $hash->{$key};
+ my ($self, $base_hash, $hash, $prefix) = @_;
+ foreach my $key (keys %$hash) {
+ if (ref($hash->{$key}) eq 'HASH') {
+ $self->_flatten_hash($base_hash, $hash->{$key}, $prefix . "_$key");
+ }
+ elsif (ref($hash->{$key}) ne 'ARRAY') {
+ $base_hash->{$prefix . "_$key"} = $hash->{$key};
}
+ delete $hash->{$key};
+ }
}
sub _add_ldap_logins {
- my ($self, $rh, $cache) = @_;
- if (exists $rh->{login}) {
- my $login = $rh->{login};
- $cache->{$login} ||= $self->_bmo_to_ldap($login);
- Bugzilla->push_ext->logger->debug("BMO($login) --> LDAP(" . $cache->{$login} . ")");
- $rh->{ldap} = $cache->{$login};
- }
- foreach my $key (keys %$rh) {
- next unless ref($rh->{$key}) eq 'HASH';
- $self->_add_ldap_logins($rh->{$key}, $cache);
- }
+ my ($self, $rh, $cache) = @_;
+ if (exists $rh->{login}) {
+ my $login = $rh->{login};
+ $cache->{$login} ||= $self->_bmo_to_ldap($login);
+ Bugzilla->push_ext->logger->debug(
+ "BMO($login) --> LDAP(" . $cache->{$login} . ")");
+ $rh->{ldap} = $cache->{$login};
+ }
+ foreach my $key (keys %$rh) {
+ next unless ref($rh->{$key}) eq 'HASH';
+ $self->_add_ldap_logins($rh->{$key}, $cache);
+ }
}
sub _bmo_to_ldap {
- my ($self, $login) = @_;
- my $ldap = $self->_ldap_cache();
+ my ($self, $login) = @_;
+ my $ldap = $self->_ldap_cache();
- return '' unless $login =~ /\@mozilla\.(?:com|org)$/;
+ return '' unless $login =~ /\@mozilla\.(?:com|org)$/;
- foreach my $check ($login, canon_email($login)) {
- # check for matching bugmail entry
- foreach my $mail (keys %$ldap) {
- next unless $ldap->{$mail}{bugmail_canon} eq $check;
- return $mail;
- }
+ foreach my $check ($login, canon_email($login)) {
- # check for matching mail
- if (exists $ldap->{$check}) {
- return $check;
- }
+ # check for matching bugmail entry
+ foreach my $mail (keys %$ldap) {
+ next unless $ldap->{$mail}{bugmail_canon} eq $check;
+ return $mail;
+ }
- # check for matching email alias
- foreach my $mail (sort keys %$ldap) {
- next unless grep { $check eq $_ } @{$ldap->{$mail}{aliases}};
- return $mail;
- }
+ # check for matching mail
+ if (exists $ldap->{$check}) {
+ return $check;
+ }
+
+ # check for matching email alias
+ foreach my $mail (sort keys %$ldap) {
+ next unless grep { $check eq $_ } @{$ldap->{$mail}{aliases}};
+ return $mail;
}
+ }
- return '';
+ return '';
}
sub _ldap_cache {
- my ($self) = @_;
- my $logger = Bugzilla->push_ext->logger;
- my $config = $self->config;
-
- # cache of all ldap entries; updated infrequently
- if (!$self->{ldap_cache_time} || (time) - $self->{ldap_cache_time} > $config->{ldap_poll} * 60) {
- $logger->debug('refreshing LDAP cache');
-
- my $cache = {};
-
- my $host = $config->{ldap_host};
- trick_taint($host);
- my $scheme = lc($config->{ldap_scheme});
- my $ldap = Net::LDAP->new($host, scheme => $scheme, onerror => 'die')
- or die $!;
- $ldap->bind($config->{ldap_user}, password => $config->{ldap_pass});
- foreach my $ldap_base ('o=com,dc=mozilla', 'o=org,dc=mozilla') {
- my $result = $ldap->search(
- base => $ldap_base,
- scope => 'sub',
- filter => '(mail=*)',
- attrs => ['mail', 'bugzillaEmail', 'emailAlias', 'cn', 'employeeType'],
- );
- foreach my $entry ($result->entries) {
- my ($name, $bugMail, $mail, $type) =
- map { $entry->get_value($_) || '' }
- qw(cn bugzillaEmail mail employeeType);
- next if $type eq 'DISABLED';
- $mail = lc $mail;
- $bugMail = '' if $bugMail !~ /\@/;
- $bugMail = trim($bugMail);
- if ($bugMail =~ / /) {
- $bugMail = (grep { /\@/ } split / /, $bugMail)[0];
- }
- $name =~ s/\s+/ /g;
- $cache->{$mail}{name} = trim($name);
- $cache->{$mail}{bugmail} = $bugMail;
- $cache->{$mail}{bugmail_canon} = canon_email($bugMail);
- $cache->{$mail}{aliases} = [];
- foreach my $alias (
- @{$entry->get_value('emailAlias', asref => 1) || []}
- ) {
- push @{$cache->{$mail}{aliases}}, canon_email($alias);
- }
- }
- }
+ my ($self) = @_;
+ my $logger = Bugzilla->push_ext->logger;
+ my $config = $self->config;
+
+ # cache of all ldap entries; updated infrequently
+ if (!$self->{ldap_cache_time}
+ || (time) - $self->{ldap_cache_time} > $config->{ldap_poll} * 60)
+ {
+ $logger->debug('refreshing LDAP cache');
- $self->{ldap_cache} = $cache;
- $self->{ldap_cache_time} = (time);
+ my $cache = {};
+
+ my $host = $config->{ldap_host};
+ trick_taint($host);
+ my $scheme = lc($config->{ldap_scheme});
+ my $ldap = Net::LDAP->new($host, scheme => $scheme, onerror => 'die') or die $!;
+ $ldap->bind($config->{ldap_user}, password => $config->{ldap_pass});
+ foreach my $ldap_base ('o=com,dc=mozilla', 'o=org,dc=mozilla') {
+ my $result = $ldap->search(
+ base => $ldap_base,
+ scope => 'sub',
+ filter => '(mail=*)',
+ attrs => ['mail', 'bugzillaEmail', 'emailAlias', 'cn', 'employeeType'],
+ );
+ foreach my $entry ($result->entries) {
+ my ($name, $bugMail, $mail, $type)
+ = map { $entry->get_value($_) || '' } qw(cn bugzillaEmail mail employeeType);
+ next if $type eq 'DISABLED';
+ $mail = lc $mail;
+ $bugMail = '' if $bugMail !~ /\@/;
+ $bugMail = trim($bugMail);
+ if ($bugMail =~ / /) {
+ $bugMail = (grep {/\@/} split / /, $bugMail)[0];
+ }
+ $name =~ s/\s+/ /g;
+ $cache->{$mail}{name} = trim($name);
+ $cache->{$mail}{bugmail} = $bugMail;
+ $cache->{$mail}{bugmail_canon} = canon_email($bugMail);
+ $cache->{$mail}{aliases} = [];
+ foreach my $alias (@{$entry->get_value('emailAlias', asref => 1) || []}) {
+ push @{$cache->{$mail}{aliases}}, canon_email($alias);
+ }
+ }
}
- return $self->{ldap_cache};
+ $self->{ldap_cache} = $cache;
+ $self->{ldap_cache_time} = (time);
+ }
+
+ return $self->{ldap_cache};
}
1;
diff --git a/extensions/Push/lib/Connector/Base.pm b/extensions/Push/lib/Connector/Base.pm
index ee41bd160..bd46fe6b4 100644
--- a/extensions/Push/lib/Connector/Base.pm
+++ b/extensions/Push/lib/Connector/Base.pm
@@ -18,59 +18,65 @@ use Bugzilla::Extension::Push::BacklogQueue;
use Bugzilla::Extension::Push::Backoff;
sub new {
- my ($class) = @_;
- my $self = {};
- bless($self, $class);
- ($self->{name}) = $class =~ /^.+:(.+)$/;
- $self->init();
- return $self;
+ my ($class) = @_;
+ my $self = {};
+ bless($self, $class);
+ ($self->{name}) = $class =~ /^.+:(.+)$/;
+ $self->init();
+ return $self;
}
sub name {
- my $self = shift;
- return $self->{name};
+ my $self = shift;
+ return $self->{name};
}
sub init {
- my ($self) = @_;
- # abstract
- # perform any initialisation here
- # will be run when created by the web pages or by the daemon
- # and also when the configuration needs to be reloaded
+ my ($self) = @_;
+
+ # abstract
+ # perform any initialisation here
+ # will be run when created by the web pages or by the daemon
+ # and also when the configuration needs to be reloaded
}
sub stop {
- my ($self) = @_;
- # abstract
- # run from the daemon only; disconnect from remote hosts, etc
+ my ($self) = @_;
+
+ # abstract
+ # run from the daemon only; disconnect from remote hosts, etc
}
sub should_send {
- my ($self, $message) = @_;
- # abstract
- # return boolean indicating if the connector will be sending the message.
- # this will be called each message, and should be a very quick simple test.
- # the connector can perform a more exhaustive test in the send() method.
- return 0;
+ my ($self, $message) = @_;
+
+ # abstract
+ # return boolean indicating if the connector will be sending the message.
+ # this will be called each message, and should be a very quick simple test.
+ # the connector can perform a more exhaustive test in the send() method.
+ return 0;
}
sub send {
- my ($self, $message) = @_;
- # abstract
- # deliver the message, daemon only
+ my ($self, $message) = @_;
+
+ # abstract
+ # deliver the message, daemon only
}
sub options {
- my ($self) = @_;
- # abstract
- # return an array of configuration variables
- return ();
+ my ($self) = @_;
+
+ # abstract
+ # return an array of configuration variables
+ return ();
}
sub options_validate {
- my ($class, $config) = @_;
- # abstract, static
- # die if a combination of options in $config is invalid
+ my ($class, $config) = @_;
+
+ # abstract, static
+ # die if a combination of options in $config is invalid
}
#
@@ -78,29 +84,30 @@ sub options_validate {
#
sub config {
- my ($self) = @_;
- if (!$self->{config}) {
- $self->load_config();
- }
- return $self->{config};
+ my ($self) = @_;
+ if (!$self->{config}) {
+ $self->load_config();
+ }
+ return $self->{config};
}
sub load_config {
- my ($self) = @_;
- my $config = Bugzilla::Extension::Push::Config->new($self->name, $self->options);
- $config->load();
- $self->{config} = $config;
+ my ($self) = @_;
+ my $config
+ = Bugzilla::Extension::Push::Config->new($self->name, $self->options);
+ $config->load();
+ $self->{config} = $config;
}
sub enabled {
- my ($self) = @_;
- return $self->config->{enabled} eq 'Enabled';
+ my ($self) = @_;
+ return $self->config->{enabled} eq 'Enabled';
}
sub backlog {
- my ($self) = @_;
- $self->{backlog} ||= Bugzilla::Extension::Push::BacklogQueue->new($self->name);
- return $self->{backlog};
+ my ($self) = @_;
+ $self->{backlog} ||= Bugzilla::Extension::Push::BacklogQueue->new($self->name);
+ return $self->{backlog};
}
1;
diff --git a/extensions/Push/lib/Connector/File.pm b/extensions/Push/lib/Connector/File.pm
index ae249ffe5..7d86953f8 100644
--- a/extensions/Push/lib/Connector/File.pm
+++ b/extensions/Push/lib/Connector/File.pm
@@ -20,51 +20,46 @@ use Encode;
use FileHandle;
sub init {
- my ($self) = @_;
+ my ($self) = @_;
}
sub options {
- return (
- {
- name => 'filename',
- label => 'Filename',
- type => 'string',
- default => 'push.log',
- required => 1,
- validate => sub {
- my $filename = shift;
- $filename =~ m#^/#
- && die "Absolute paths are not permitted\n";
- $filename =~ m#\.\.#
- && die "Relative paths are not permitted\n";
- },
- },
- );
+ return (
+ {
+ name => 'filename',
+ label => 'Filename',
+ type => 'string',
+ default => 'push.log',
+ required => 1,
+ validate => sub {
+ my $filename = shift;
+ $filename =~ m#^/# && die "Absolute paths are not permitted\n";
+ $filename =~ m#\.\.# && die "Relative paths are not permitted\n";
+ },
+ },
+ );
}
sub should_send {
- my ($self, $message) = @_;
- return 1;
+ my ($self, $message) = @_;
+ return 1;
}
sub send {
- my ($self, $message) = @_;
+ my ($self, $message) = @_;
- # pretty-format json payload
- my $payload = $message->payload_decoded;
- $payload = to_json($payload, 1);
+ # pretty-format json payload
+ my $payload = $message->payload_decoded;
+ $payload = to_json($payload, 1);
- my $filename = bz_locations()->{'datadir'} . '/' . $self->config->{filename};
- Bugzilla->push_ext->logger->debug("File: Appending to $filename");
- my $fh = FileHandle->new(">>$filename");
- $fh->binmode(':utf8');
- $fh->print(
- "[" . scalar(localtime) . "]\n" .
- $payload . "\n\n"
- );
- $fh->close;
+ my $filename = bz_locations()->{'datadir'} . '/' . $self->config->{filename};
+ Bugzilla->push_ext->logger->debug("File: Appending to $filename");
+ my $fh = FileHandle->new(">>$filename");
+ $fh->binmode(':utf8');
+ $fh->print("[" . scalar(localtime) . "]\n" . $payload . "\n\n");
+ $fh->close;
- return PUSH_RESULT_OK;
+ return PUSH_RESULT_OK;
}
1;
diff --git a/extensions/Push/lib/Connector/Phabricator.pm b/extensions/Push/lib/Connector/Phabricator.pm
index 33e2bb6ad..61a39e32b 100644
--- a/extensions/Push/lib/Connector/Phabricator.pm
+++ b/extensions/Push/lib/Connector/Phabricator.pm
@@ -29,105 +29,96 @@ use Bugzilla::Extension::Push::Constants;
use Bugzilla::Extension::Push::Util qw(is_public);
sub options {
- return (
- {
- name => 'phabricator_url',
- label => 'Phabricator URL',
- type => 'string',
- default => '',
- required => 1,
- }
- );
+ return ({
+ name => 'phabricator_url',
+ label => 'Phabricator URL',
+ type => 'string',
+ default => '',
+ required => 1,
+ });
}
sub should_send {
- my ( $self, $message ) = @_;
+ my ($self, $message) = @_;
- return 0 unless Bugzilla->params->{phabricator_enabled};
+ return 0 unless Bugzilla->params->{phabricator_enabled};
- # We are only interested currently in bug group, assignee, qa-contact, or cc changes.
- return 0
- unless $message->routing_key =~
- /^(?:attachment|bug)\.modify:.*\b(bug_group|assigned_to|qa_contact|cc)\b/;
+# We are only interested currently in bug group, assignee, qa-contact, or cc changes.
+ return 0
+ unless $message->routing_key
+ =~ /^(?:attachment|bug)\.modify:.*\b(bug_group|assigned_to|qa_contact|cc)\b/;
- my $bug = $self->_get_bug_by_data( $message->payload_decoded ) || return 0;
+ my $bug = $self->_get_bug_by_data($message->payload_decoded) || return 0;
- return $bug->has_attachment_with_mimetype(PHAB_CONTENT_TYPE);
+ return $bug->has_attachment_with_mimetype(PHAB_CONTENT_TYPE);
}
sub send {
- my ( $self, $message ) = @_;
-
- my $logger = Bugzilla->push_ext->logger;
-
- my $data = $message->payload_decoded;
-
- my $bug = $self->_get_bug_by_data($data) || return PUSH_RESULT_OK;
-
- my $is_public = is_public($bug);
-
- my $revisions = get_attachment_revisions($bug);
-
- my $group_change =
- ($message->routing_key =~ /^(?:attachment|bug)\.modify:.*\bbug_group\b/)
- ? 1
- : 0;
-
- foreach my $revision (@$revisions) {
- if ( $is_public && $group_change ) {
- Bugzilla->audit(sprintf(
- 'Making revision %s public for bug %s',
- $revision->id,
- $bug->id
- ));
- $revision->make_public();
- }
- elsif ( !$is_public && $group_change ) {
- Bugzilla->audit(sprintf(
- 'Giving revision %s a custom policy for bug %s',
- $revision->id,
- $bug->id
- ));
- my $set_project_names = [ map { "bmo-" . $_->name } @{ $bug->groups_in } ];
- $revision->make_private($set_project_names);
- }
-
- # Subscriber list of the private revision should always match
- # the bug roles such as assignee, qa contact, and cc members.
- if (!$is_public) {
- Bugzilla->audit(sprintf(
- 'Updating subscribers for %s for bug %s',
- $revision->id,
- $bug->id
- ));
- my $subscribers = get_bug_role_phids($bug);
- $revision->set_subscribers($subscribers) if $subscribers;
- }
-
- $revision->update();
+ my ($self, $message) = @_;
+
+ my $logger = Bugzilla->push_ext->logger;
+
+ my $data = $message->payload_decoded;
+
+ my $bug = $self->_get_bug_by_data($data) || return PUSH_RESULT_OK;
+
+ my $is_public = is_public($bug);
+
+ my $revisions = get_attachment_revisions($bug);
+
+ my $group_change
+ = ($message->routing_key =~ /^(?:attachment|bug)\.modify:.*\bbug_group\b/)
+ ? 1
+ : 0;
+
+ foreach my $revision (@$revisions) {
+ if ($is_public && $group_change) {
+ Bugzilla->audit(
+ sprintf('Making revision %s public for bug %s', $revision->id, $bug->id));
+ $revision->make_public();
}
+ elsif (!$is_public && $group_change) {
+ Bugzilla->audit(sprintf(
+ 'Giving revision %s a custom policy for bug %s',
+ $revision->id, $bug->id
+ ));
+ my $set_project_names = [map { "bmo-" . $_->name } @{$bug->groups_in}];
+ $revision->make_private($set_project_names);
+ }
+
+ # Subscriber list of the private revision should always match
+ # the bug roles such as assignee, qa contact, and cc members.
+ if (!$is_public) {
+ Bugzilla->audit(
+ sprintf('Updating subscribers for %s for bug %s', $revision->id, $bug->id));
+ my $subscribers = get_bug_role_phids($bug);
+ $revision->set_subscribers($subscribers) if $subscribers;
+ }
+
+ $revision->update();
+ }
- return PUSH_RESULT_OK;
+ return PUSH_RESULT_OK;
}
sub _get_bug_by_data {
- my ( $self, $data ) = @_;
- my $bug_data = $self->_get_bug_data($data) || return 0;
- my $bug = Bugzilla::Bug->new( { id => $bug_data->{id} } );
+ my ($self, $data) = @_;
+ my $bug_data = $self->_get_bug_data($data) || return 0;
+ my $bug = Bugzilla::Bug->new({id => $bug_data->{id}});
}
sub _get_bug_data {
- my ( $self, $data ) = @_;
- my $target = $data->{event}->{target};
- if ( $target eq 'bug' ) {
- return $data->{bug};
- }
- elsif ( exists $data->{$target}->{bug} ) {
- return $data->{$target}->{bug};
- }
- else {
- return;
- }
+ my ($self, $data) = @_;
+ my $target = $data->{event}->{target};
+ if ($target eq 'bug') {
+ return $data->{bug};
+ }
+ elsif (exists $data->{$target}->{bug}) {
+ return $data->{$target}->{bug};
+ }
+ else {
+ return;
+ }
}
1;
diff --git a/extensions/Push/lib/Connector/Spark.pm b/extensions/Push/lib/Connector/Spark.pm
index e58ddfbe4..1eb6f22c6 100644
--- a/extensions/Push/lib/Connector/Spark.pm
+++ b/extensions/Push/lib/Connector/Spark.pm
@@ -25,150 +25,154 @@ use LWP::UserAgent;
use List::MoreUtils qw(any);
sub options {
- return (
- {
- name => 'spark_endpoint',
- label => 'Spark API Endpoint',
- type => 'string',
- default => 'https://api.ciscospark.com/v1',
- required => 1,
- },
- {
- name => 'spark_room_id',
- label => 'Spark Room ID',
- type => 'string',
- default => 'bugzilla',
- required => 1,
- },
- {
- name => 'spark_api_key',
- label => 'Spark API Key',
- type => 'string',
- default => '',
- required => 1,
- },
- );
+ return (
+ {
+ name => 'spark_endpoint',
+ label => 'Spark API Endpoint',
+ type => 'string',
+ default => 'https://api.ciscospark.com/v1',
+ required => 1,
+ },
+ {
+ name => 'spark_room_id',
+ label => 'Spark Room ID',
+ type => 'string',
+ default => 'bugzilla',
+ required => 1,
+ },
+ {
+ name => 'spark_api_key',
+ label => 'Spark API Key',
+ type => 'string',
+ default => '',
+ required => 1,
+ },
+ );
}
sub stop {
- my ($self) = @_;
+ my ($self) = @_;
}
sub should_send {
- my ($self, $message) = @_;
-
- my $data = $message->payload_decoded;
- my $bug_data = $self->_get_bug_data($data)
- || return 0;
-
- # Send if bug has cisco-spark keyword
- my $bug = Bugzilla::Bug->new({ id => $bug_data->{id}, cache => 1 });
- return 0 unless $bug->has_keyword('cisco-spark');
-
- if ($message->routing_key eq 'bug.create') {
- return 1;
- }
- else {
- foreach my $change (@{ $data->{event}->{changes} }) {
- # send status and resolution updates
- return 1 if $change->{field} eq 'bug_status' || $change->{field} eq 'resolution';
- # also send if the right keyword has been added to this bug
- if ($change->{field} eq 'keywords' && $change->{added}) {
- my @added = split(/, /, $change->{added});
- return 1 if any { $_ eq 'cisco-spark' } @added;
- }
- }
+ my ($self, $message) = @_;
+
+ my $data = $message->payload_decoded;
+ my $bug_data = $self->_get_bug_data($data) || return 0;
+
+ # Send if bug has cisco-spark keyword
+ my $bug = Bugzilla::Bug->new({id => $bug_data->{id}, cache => 1});
+ return 0 unless $bug->has_keyword('cisco-spark');
+
+ if ($message->routing_key eq 'bug.create') {
+ return 1;
+ }
+ else {
+ foreach my $change (@{$data->{event}->{changes}}) {
+
+ # send status and resolution updates
+ return 1
+ if $change->{field} eq 'bug_status' || $change->{field} eq 'resolution';
+
+ # also send if the right keyword has been added to this bug
+ if ($change->{field} eq 'keywords' && $change->{added}) {
+ my @added = split(/, /, $change->{added});
+ return 1 if any { $_ eq 'cisco-spark' } @added;
+ }
}
+ }
- # and nothing else
- return 0;
+ # and nothing else
+ return 0;
}
sub send {
- my ($self, $message) = @_;
+ my ($self, $message) = @_;
- eval {
- my $data = $message->payload_decoded();
- my $bug_data = $self->_get_bug_data($data);
- my $bug = Bugzilla::Bug->new({ id => $bug_data->{id}, cache => 1 });
+ eval {
+ my $data = $message->payload_decoded();
+ my $bug_data = $self->_get_bug_data($data);
+ my $bug = Bugzilla::Bug->new({id => $bug_data->{id}, cache => 1});
- my $text = "Bug " . $bug->id . " - " . $bug->short_desc . "\n";
- if ($message->routing_key eq 'bug.create') {
- $text = "New " . $text;
+ my $text = "Bug " . $bug->id . " - " . $bug->short_desc . "\n";
+ if ($message->routing_key eq 'bug.create') {
+ $text = "New " . $text;
+ }
+ else {
+ foreach my $change (@{$data->{event}->{changes}}) {
+ if ($change->{field} eq 'bug_status') {
+ $text
+ .= "Status changed: " . $change->{removed} . " -> " . $change->{added} . "\n";
}
- else {
- foreach my $change (@{ $data->{event}->{changes} }) {
- if ($change->{field} eq 'bug_status') {
- $text .= "Status changed: " .
- $change->{removed} . " -> " . $change->{added} . "\n";
- }
- if ($change->{field} eq 'resolution') {
- $text .= "Resolution changed: " .
- ($change->{removed} ? $change->{removed} . " -> " : "") . $change->{added} . "\n";
- }
- }
+ if ($change->{field} eq 'resolution') {
+ $text
+ .= "Resolution changed: "
+ . ($change->{removed} ? $change->{removed} . " -> " : "")
+ . $change->{added} . "\n";
}
- $text .= Bugzilla->localconfig->{urlbase} . "show_bug.cgi?id=" . $bug->id;
+ }
+ }
+ $text .= Bugzilla->localconfig->{urlbase} . "show_bug.cgi?id=" . $bug->id;
- my $room_id = $self->config->{spark_room_id};
- my $message_uri = $self->_spark_uri('messages');
+ my $room_id = $self->config->{spark_room_id};
+ my $message_uri = $self->_spark_uri('messages');
- my $json_data = { roomId => $room_id, text => $text };
+ my $json_data = {roomId => $room_id, text => $text};
- my $headers = HTTP::Headers->new(
- Content_Type => 'application/json'
- );
- my $request = HTTP::Request->new('POST', $message_uri, $headers, encode_json($json_data));
- my $resp = $self->_user_agent->request($request);
+ my $headers = HTTP::Headers->new(Content_Type => 'application/json');
+ my $request
+ = HTTP::Request->new('POST', $message_uri, $headers, encode_json($json_data));
+ my $resp = $self->_user_agent->request($request);
- if ($resp->code != 200) {
- die "Expected HTTP 200 response, got " . $resp->code;
- }
- };
- if ($@) {
- return (PUSH_RESULT_TRANSIENT, clean_error($@));
+ if ($resp->code != 200) {
+ die "Expected HTTP 200 response, got " . $resp->code;
}
+ };
+ if ($@) {
+ return (PUSH_RESULT_TRANSIENT, clean_error($@));
+ }
- return PUSH_RESULT_OK;
+ return PUSH_RESULT_OK;
}
# Private methods
sub _get_bug_data {
- my ($self, $data) = @_;
- my $target = $data->{event}->{target};
- if ($target eq 'bug') {
- return $data->{bug};
- } elsif (exists $data->{$target}->{bug}) {
- return $data->{$target}->{bug};
- } else {
- return;
- }
+ my ($self, $data) = @_;
+ my $target = $data->{event}->{target};
+ if ($target eq 'bug') {
+ return $data->{bug};
+ }
+ elsif (exists $data->{$target}->{bug}) {
+ return $data->{$target}->{bug};
+ }
+ else {
+ return;
+ }
}
sub _user_agent {
- my ($self) = @_;
- my $ua = LWP::UserAgent->new(agent => 'Bugzilla');
- $ua->timeout(10);
- $ua->protocols_allowed(['http', 'https']);
-
- if (my $proxy_url = Bugzilla->params->{proxy_url}) {
- $ua->proxy(['http', 'https'], $proxy_url);
- }
- else {
- $ua->env_proxy();
- }
-
- $ua->default_header(
- 'Authorization' => 'Bearer ' . $self->config->{spark_api_key}
- );
-
- return $ua;
+ my ($self) = @_;
+ my $ua = LWP::UserAgent->new(agent => 'Bugzilla');
+ $ua->timeout(10);
+ $ua->protocols_allowed(['http', 'https']);
+
+ if (my $proxy_url = Bugzilla->params->{proxy_url}) {
+ $ua->proxy(['http', 'https'], $proxy_url);
+ }
+ else {
+ $ua->env_proxy();
+ }
+
+ $ua->default_header(
+ 'Authorization' => 'Bearer ' . $self->config->{spark_api_key});
+
+ return $ua;
}
sub _spark_uri {
- my ($self, $path) = @_;
- return URI->new($self->config->{spark_endpoint} . "/" . $path);
+ my ($self, $path) = @_;
+ return URI->new($self->config->{spark_endpoint} . "/" . $path);
}
1;
diff --git a/extensions/Push/lib/Connectors.pm b/extensions/Push/lib/Connectors.pm
index d3c55d3ca..9a3856c02 100644
--- a/extensions/Push/lib/Connectors.pm
+++ b/extensions/Push/lib/Connectors.pm
@@ -19,94 +19,97 @@ use File::Basename;
use Try::Tiny;
sub new {
- my ($class) = @_;
- my $self = {};
- bless($self, $class);
-
- $self->{names} = [];
- $self->{objects} = {};
- $self->{path} = bz_locations->{'extensionsdir'} . '/Push/lib/Connector';
-
- foreach my $file (glob($self->{path} . '/*.pm')) {
- my $name = basename($file);
- $name =~ s/\.pm$//;
- next if $name eq 'Base';
- if (length($name) > 32) {
- WARN("Ignoring connector '$name': Name longer than 32 characters");
- }
- push @{$self->{names}}, $name;
- TRACE("Found connector '$name'");
+ my ($class) = @_;
+ my $self = {};
+ bless($self, $class);
+
+ $self->{names} = [];
+ $self->{objects} = {};
+ $self->{path} = bz_locations->{'extensionsdir'} . '/Push/lib/Connector';
+
+ foreach my $file (glob($self->{path} . '/*.pm')) {
+ my $name = basename($file);
+ $name =~ s/\.pm$//;
+ next if $name eq 'Base';
+ if (length($name) > 32) {
+ WARN("Ignoring connector '$name': Name longer than 32 characters");
}
+ push @{$self->{names}}, $name;
+ TRACE("Found connector '$name'");
+ }
- return $self;
+ return $self;
}
sub _load {
- my ($self) = @_;
- return if scalar keys %{$self->{objects}};
-
- foreach my $name (@{$self->{names}}) {
- next if exists $self->{objects}->{$name};
- my $file = $self->{path} . "/$name.pm";
- trick_taint($file);
- require $file;
- my $package = "Bugzilla::Extension::Push::Connector::$name";
-
- TRACE("Loading connector '$name'");
- my $old_error_mode = Bugzilla->error_mode;
- Bugzilla->error_mode(ERROR_MODE_DIE);
- try {
- my $connector = $package->new();
- $connector->load_config();
- $self->{objects}->{$name} = $connector;
- } catch {
- ERROR("Connector '$name' failed to load: " . clean_error($_));
- };
- Bugzilla->error_mode($old_error_mode);
+ my ($self) = @_;
+ return if scalar keys %{$self->{objects}};
+
+ foreach my $name (@{$self->{names}}) {
+ next if exists $self->{objects}->{$name};
+ my $file = $self->{path} . "/$name.pm";
+ trick_taint($file);
+ require $file;
+ my $package = "Bugzilla::Extension::Push::Connector::$name";
+
+ TRACE("Loading connector '$name'");
+ my $old_error_mode = Bugzilla->error_mode;
+ Bugzilla->error_mode(ERROR_MODE_DIE);
+ try {
+ my $connector = $package->new();
+ $connector->load_config();
+ $self->{objects}->{$name} = $connector;
}
+ catch {
+ ERROR("Connector '$name' failed to load: " . clean_error($_));
+ };
+ Bugzilla->error_mode($old_error_mode);
+ }
}
sub stop {
- my ($self) = @_;
- foreach my $connector ($self->list) {
- next unless $connector->enabled;
- TRACE("Stopping '" . $connector->name . "'");
- try {
- $connector->stop();
- } catch {
- ERROR("Connector '" . $connector->name . "' failed to stop: " . clean_error($_));
- };
+ my ($self) = @_;
+ foreach my $connector ($self->list) {
+ next unless $connector->enabled;
+ TRACE("Stopping '" . $connector->name . "'");
+ try {
+ $connector->stop();
}
+ catch {
+ ERROR(
+ "Connector '" . $connector->name . "' failed to stop: " . clean_error($_));
+ };
+ }
}
sub reload {
- my ($self) = @_;
- $self->stop();
- $self->{objects} = {};
- $self->_load();
+ my ($self) = @_;
+ $self->stop();
+ $self->{objects} = {};
+ $self->_load();
}
sub names {
- my ($self) = @_;
- return @{$self->{names}};
+ my ($self) = @_;
+ return @{$self->{names}};
}
sub list {
- my ($self) = @_;
- $self->_load();
- return sort { $a->name cmp $b->name } values %{$self->{objects}};
+ my ($self) = @_;
+ $self->_load();
+ return sort { $a->name cmp $b->name } values %{$self->{objects}};
}
sub exists {
- my ($self, $name) = @_;
- $self->by_name($name) ? 1 : 0;
+ my ($self, $name) = @_;
+ $self->by_name($name) ? 1 : 0;
}
sub by_name {
- my ($self, $name) = @_;
- $self->_load();
- return unless exists $self->{objects}->{$name};
- return $self->{objects}->{$name};
+ my ($self, $name) = @_;
+ $self->_load();
+ return unless exists $self->{objects}->{$name};
+ return $self->{objects}->{$name};
}
1;
diff --git a/extensions/Push/lib/Constants.pm b/extensions/Push/lib/Constants.pm
index 09c5e464c..c021b32f4 100644
--- a/extensions/Push/lib/Constants.pm
+++ b/extensions/Push/lib/Constants.pm
@@ -14,14 +14,14 @@ use warnings;
use base 'Exporter';
our @EXPORT = qw(
- PUSH_RESULT_OK
- PUSH_RESULT_IGNORED
- PUSH_RESULT_TRANSIENT
- PUSH_RESULT_ERROR
- PUSH_RESULT_UNKNOWN
- push_result_to_string
-
- POLL_INTERVAL_SECONDS
+ PUSH_RESULT_OK
+ PUSH_RESULT_IGNORED
+ PUSH_RESULT_TRANSIENT
+ PUSH_RESULT_ERROR
+ PUSH_RESULT_UNKNOWN
+ push_result_to_string
+
+ POLL_INTERVAL_SECONDS
);
use constant PUSH_RESULT_OK => 1;
@@ -31,12 +31,12 @@ use constant PUSH_RESULT_ERROR => 4;
use constant PUSH_RESULT_UNKNOWN => 5;
sub push_result_to_string {
- my ($result) = @_;
- return 'OK' if $result == PUSH_RESULT_OK;
- return 'OK-IGNORED' if $result == PUSH_RESULT_IGNORED;
- return 'TRANSIENT-ERROR' if $result == PUSH_RESULT_TRANSIENT;
- return 'FATAL-ERROR' if $result == PUSH_RESULT_ERROR;
- return 'UNKNOWN' if $result == PUSH_RESULT_UNKNOWN;
+ my ($result) = @_;
+ return 'OK' if $result == PUSH_RESULT_OK;
+ return 'OK-IGNORED' if $result == PUSH_RESULT_IGNORED;
+ return 'TRANSIENT-ERROR' if $result == PUSH_RESULT_TRANSIENT;
+ return 'FATAL-ERROR' if $result == PUSH_RESULT_ERROR;
+ return 'UNKNOWN' if $result == PUSH_RESULT_UNKNOWN;
}
use constant POLL_INTERVAL_SECONDS => 30;
diff --git a/extensions/Push/lib/Daemon.pm b/extensions/Push/lib/Daemon.pm
index 7f2459a95..7fb5352ca 100644
--- a/extensions/Push/lib/Daemon.pm
+++ b/extensions/Push/lib/Daemon.pm
@@ -20,7 +20,7 @@ use File::Basename;
use Pod::Usage;
sub start {
- newdaemon();
+ newdaemon();
}
#
@@ -28,70 +28,71 @@ sub start {
#
sub gd_preconfig {
- my $self = shift;
- my $pidfile = $self->{gd_args}{pidfile};
- if (!$pidfile) {
- $pidfile = bz_locations()->{datadir} . '/' . $self->{gd_progname} . ".pid";
- }
- return (pidfile => $pidfile);
+ my $self = shift;
+ my $pidfile = $self->{gd_args}{pidfile};
+ if (!$pidfile) {
+ $pidfile = bz_locations()->{datadir} . '/' . $self->{gd_progname} . ".pid";
+ }
+ return (pidfile => $pidfile);
}
sub gd_getopt {
- my $self = shift;
- $self->SUPER::gd_getopt();
- if ($self->{gd_args}{progname}) {
- $self->{gd_progname} = $self->{gd_args}{progname};
- } else {
- $self->{gd_progname} = basename($0);
- }
- $self->{_original_zero} = $0;
- $0 = $self->{gd_progname};
+ my $self = shift;
+ $self->SUPER::gd_getopt();
+ if ($self->{gd_args}{progname}) {
+ $self->{gd_progname} = $self->{gd_args}{progname};
+ }
+ else {
+ $self->{gd_progname} = basename($0);
+ }
+ $self->{_original_zero} = $0;
+ $0 = $self->{gd_progname};
}
sub gd_postconfig {
- my $self = shift;
- $0 = delete $self->{_original_zero};
+ my $self = shift;
+ $0 = delete $self->{_original_zero};
}
sub gd_more_opt {
- my $self = shift;
- return (
- 'pidfile=s' => \$self->{gd_args}{pidfile},
- 'n=s' => \$self->{gd_args}{progname},
- );
+ my $self = shift;
+ return (
+ 'pidfile=s' => \$self->{gd_args}{pidfile},
+ 'n=s' => \$self->{gd_args}{progname},
+ );
}
sub gd_usage {
- pod2usage({ -verbose => 0, -exitval => 'NOEXIT' });
- return 0;
-};
+ pod2usage({-verbose => 0, -exitval => 'NOEXIT'});
+ return 0;
+}
sub gd_redirect_output {
- my $self = shift;
+ my $self = shift;
- my $filename = bz_locations()->{datadir} . '/' . $self->{gd_progname} . ".log";
+ my $filename = bz_locations()->{datadir} . '/' . $self->{gd_progname} . ".log";
+ open(STDERR, ">>", $filename) or (print "could not open stderr: $!" && exit(1));
+ close(STDOUT);
+ open(STDOUT, ">&", STDERR) or die "redirect STDOUT -> STDERR: $!";
+ $SIG{HUP} = sub {
+ close(STDERR);
open(STDERR, ">>", $filename) or (print "could not open stderr: $!" && exit(1));
- close(STDOUT);
- open(STDOUT, ">&", STDERR) or die "redirect STDOUT -> STDERR: $!";
- $SIG{HUP} = sub {
- close(STDERR);
- open(STDERR, ">>", $filename) or (print "could not open stderr: $!" && exit(1));
- };
+ };
}
sub gd_setup_signals {
- my $self = shift;
- $self->SUPER::gd_setup_signals();
- $SIG{TERM} = sub { $self->gd_quit_event(); }
+ my $self = shift;
+ $self->SUPER::gd_setup_signals();
+ $SIG{TERM} = sub { $self->gd_quit_event(); }
}
sub gd_run {
- my $self = shift;
- $::SIG{__DIE__} = \&Carp::confess if $self->{debug};
- my $push = Bugzilla->push_ext;
- $push->logger->{debug} = $self->{debug};
- $push->is_daemon(1);
- $push->start();
+ my $self = shift;
+ $::SIG{__DIE__} = \&Carp::confess if $self->{debug};
+ my $push = Bugzilla->push_ext;
+ $push->logger->{debug} = $self->{debug};
+ $push->is_daemon(1);
+ $push->start();
}
1;
diff --git a/extensions/Push/lib/Log.pm b/extensions/Push/lib/Log.pm
index 8a35a6cf5..7358477ed 100644
--- a/extensions/Push/lib/Log.pm
+++ b/extensions/Push/lib/Log.pm
@@ -15,32 +15,30 @@ use Bugzilla;
use Bugzilla::Extension::Push::Message;
sub new {
- my ($class) = @_;
- my $self = {};
- bless($self, $class);
- return $self;
+ my ($class) = @_;
+ my $self = {};
+ bless($self, $class);
+ return $self;
}
sub count {
- my ($self) = @_;
- my $dbh = Bugzilla->dbh;
- return $dbh->selectrow_array("SELECT COUNT(*) FROM push_log");
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+ return $dbh->selectrow_array("SELECT COUNT(*) FROM push_log");
}
sub list {
- my ($self, %args) = @_;
- $args{limit} ||= 10;
- $args{filter} ||= '';
- my @result;
- my $dbh = Bugzilla->dbh;
+ my ($self, %args) = @_;
+ $args{limit} ||= 10;
+ $args{filter} ||= '';
+ my @result;
+ my $dbh = Bugzilla->dbh;
- my $ids = $dbh->selectcol_arrayref("
+ my $ids = $dbh->selectcol_arrayref("
SELECT id
FROM push_log
- ORDER BY processed_ts DESC " .
- $dbh->sql_limit(100)
- );
- return Bugzilla::Extension::Push::LogEntry->new_from_list($ids);
+ ORDER BY processed_ts DESC " . $dbh->sql_limit(100));
+ return Bugzilla::Extension::Push::LogEntry->new_from_list($ids);
}
1;
diff --git a/extensions/Push/lib/LogEntry.pm b/extensions/Push/lib/LogEntry.pm
index f4e894b94..0d9770a8a 100644
--- a/extensions/Push/lib/LogEntry.pm
+++ b/extensions/Push/lib/LogEntry.pm
@@ -26,21 +26,19 @@ use Bugzilla::Extension::Push::Constants;
# initialisation
#
-use constant DB_TABLE => 'push_log';
+use constant DB_TABLE => 'push_log';
use constant DB_COLUMNS => qw(
- id
- message_id
- change_set
- routing_key
- connector
- push_ts
- processed_ts
- result
- data
+ id
+ message_id
+ change_set
+ routing_key
+ connector
+ push_ts
+ processed_ts
+ result
+ data
);
-use constant VALIDATORS => {
- data => \&_check_data,
-};
+use constant VALIDATORS => {data => \&_check_data,};
use constant NAME_FIELD => '';
use constant LIST_ORDER => 'processed_ts DESC';
@@ -48,14 +46,14 @@ use constant LIST_ORDER => 'processed_ts DESC';
# accessors
#
-sub message_id { return $_[0]->{'message_id'}; }
-sub change_set { return $_[0]->{'change_set'}; }
-sub routing_key { return $_[0]->{'routing_key'}; }
-sub connector { return $_[0]->{'connector'}; }
-sub push_ts { return $_[0]->{'push_ts'}; }
+sub message_id { return $_[0]->{'message_id'}; }
+sub change_set { return $_[0]->{'change_set'}; }
+sub routing_key { return $_[0]->{'routing_key'}; }
+sub connector { return $_[0]->{'connector'}; }
+sub push_ts { return $_[0]->{'push_ts'}; }
sub processed_ts { return $_[0]->{'processed_ts'}; }
-sub result { return $_[0]->{'result'}; }
-sub data { return $_[0]->{'data'}; }
+sub result { return $_[0]->{'result'}; }
+sub data { return $_[0]->{'data'}; }
sub result_string { return push_result_to_string($_[0]->result) }
@@ -64,8 +62,8 @@ sub result_string { return push_result_to_string($_[0]->result) }
#
sub _check_data {
- my ($invocant, $value) = @_;
- return $value eq '' ? undef : $value;
+ my ($invocant, $value) = @_;
+ return $value eq '' ? undef : $value;
}
1;
diff --git a/extensions/Push/lib/Logger.pm b/extensions/Push/lib/Logger.pm
index 5d92010ee..ec6dbe497 100644
--- a/extensions/Push/lib/Logger.pm
+++ b/extensions/Push/lib/Logger.pm
@@ -20,42 +20,38 @@ use Bugzilla::Extension::Push::LogEntry;
Log::Log4perl->wrapper_register(__PACKAGE__);
sub info {
- my ($this, $message) = @_;
- INFO($message);
+ my ($this, $message) = @_;
+ INFO($message);
}
sub error {
- my ($this, $message) = @_;
- ERROR($message);
+ my ($this, $message) = @_;
+ ERROR($message);
}
sub debug {
- my ($this, $message) = @_;
- DEBUG($message);
+ my ($this, $message) = @_;
+ DEBUG($message);
}
sub result {
- my ($self, $connector, $message, $result, $data) = @_;
- $data ||= '';
-
- my $log_msg = sprintf
- '%s: Message #%s: %s %s',
- $connector->name,
- $message->message_id,
- push_result_to_string($result),
- $data;
- $self->info($log_msg);
-
- Bugzilla::Extension::Push::LogEntry->create({
- message_id => $message->message_id,
- change_set => $message->change_set,
- routing_key => $message->routing_key,
- connector => $connector->name,
- push_ts => $message->push_ts,
- processed_ts => Bugzilla->dbh->selectrow_array('SELECT NOW()'),
- result => $result,
- data => $data,
- });
+ my ($self, $connector, $message, $result, $data) = @_;
+ $data ||= '';
+
+ my $log_msg = sprintf '%s: Message #%s: %s %s', $connector->name,
+ $message->message_id, push_result_to_string($result), $data;
+ $self->info($log_msg);
+
+ Bugzilla::Extension::Push::LogEntry->create({
+ message_id => $message->message_id,
+ change_set => $message->change_set,
+ routing_key => $message->routing_key,
+ connector => $connector->name,
+ push_ts => $message->push_ts,
+ processed_ts => Bugzilla->dbh->selectrow_array('SELECT NOW()'),
+ result => $result,
+ data => $data,
+ });
}
sub _build_logger { Log::Log4perl->get_logger(__PACKAGE__); }
diff --git a/extensions/Push/lib/Message.pm b/extensions/Push/lib/Message.pm
index 1beb18ef0..3587de1d9 100644
--- a/extensions/Push/lib/Message.pm
+++ b/extensions/Push/lib/Message.pm
@@ -27,50 +27,50 @@ use Encode;
# initialisation
#
-use constant DB_TABLE => 'push';
+use constant DB_TABLE => 'push';
use constant DB_COLUMNS => qw(
- id
- push_ts
- payload
- change_set
- routing_key
+ id
+ push_ts
+ payload
+ change_set
+ routing_key
);
use constant LIST_ORDER => 'push_ts';
use constant VALIDATORS => {
- push_ts => \&_check_push_ts,
- payload => \&_check_payload,
- change_set => \&_check_change_set,
- routing_key => \&_check_routing_key,
+ push_ts => \&_check_push_ts,
+ payload => \&_check_payload,
+ change_set => \&_check_change_set,
+ routing_key => \&_check_routing_key,
};
# this creates an object which doesn't exist on the database
sub new_transient {
- my $invocant = shift;
- my $class = ref($invocant) || $invocant;
- my $object = shift;
- bless($object, $class) if $object;
- return $object;
+ my $invocant = shift;
+ my $class = ref($invocant) || $invocant;
+ my $object = shift;
+ bless($object, $class) if $object;
+ return $object;
}
# take a transient object and commit
sub create_from_transient {
- my ($self) = @_;
- return $self->create($self);
+ my ($self) = @_;
+ return $self->create($self);
}
#
# accessors
#
-sub push_ts { return $_[0]->{'push_ts'}; }
-sub payload { return $_[0]->{'payload'}; }
-sub change_set { return $_[0]->{'change_set'}; }
+sub push_ts { return $_[0]->{'push_ts'}; }
+sub payload { return $_[0]->{'payload'}; }
+sub change_set { return $_[0]->{'change_set'}; }
sub routing_key { return $_[0]->{'routing_key'}; }
-sub message_id { return $_[0]->id; }
+sub message_id { return $_[0]->id; }
sub payload_decoded {
- my ($self) = @_;
- return from_json($self->{'payload'});
+ my ($self) = @_;
+ return from_json($self->{'payload'});
}
#
@@ -78,27 +78,29 @@ sub payload_decoded {
#
sub _check_push_ts {
- my ($invocant, $value) = @_;
- $value ||= Bugzilla->dbh->selectrow_array('SELECT NOW()');
- return $value;
+ my ($invocant, $value) = @_;
+ $value ||= Bugzilla->dbh->selectrow_array('SELECT NOW()');
+ return $value;
}
sub _check_payload {
- my ($invocant, $value) = @_;
- length($value) || ThrowCodeError('push_invalid_payload');
- return $value;
+ my ($invocant, $value) = @_;
+ length($value) || ThrowCodeError('push_invalid_payload');
+ return $value;
}
sub _check_change_set {
- my ($invocant, $value) = @_;
- (defined($value) && length($value)) || ThrowCodeError('push_invalid_change_set');
- return $value;
+ my ($invocant, $value) = @_;
+ (defined($value) && length($value))
+ || ThrowCodeError('push_invalid_change_set');
+ return $value;
}
sub _check_routing_key {
- my ($invocant, $value) = @_;
- (defined($value) && length($value)) || ThrowCodeError('push_invalid_routing_key');
- return $value;
+ my ($invocant, $value) = @_;
+ (defined($value) && length($value))
+ || ThrowCodeError('push_invalid_routing_key');
+ return $value;
}
1;
diff --git a/extensions/Push/lib/Option.pm b/extensions/Push/lib/Option.pm
index a08e4c11d..a8e67714c 100644
--- a/extensions/Push/lib/Option.pm
+++ b/extensions/Push/lib/Option.pm
@@ -21,27 +21,25 @@ use Bugzilla::Util;
# initialisation
#
-use constant DB_TABLE => 'push_options';
+use constant DB_TABLE => 'push_options';
use constant DB_COLUMNS => qw(
- id
- connector
- option_name
- option_value
+ id
+ connector
+ option_name
+ option_value
);
use constant UPDATE_COLUMNS => qw(
- option_value
+ option_value
);
-use constant VALIDATORS => {
- connector => \&_check_connector,
-};
+use constant VALIDATORS => {connector => \&_check_connector,};
use constant LIST_ORDER => 'connector';
#
# accessors
#
-sub connector { return $_[0]->{'connector'}; }
-sub name { return $_[0]->{'option_name'}; }
+sub connector { return $_[0]->{'connector'}; }
+sub name { return $_[0]->{'option_name'}; }
sub value { return $_[0]->{'option_value'}; }
#
@@ -55,12 +53,12 @@ sub set_value { $_[0]->{'option_value'} = $_[1]; }
#
sub _check_connector {
- my ($invocant, $value) = @_;
- $value eq '*'
- || $value eq 'global'
- || Bugzilla->push_ext->connectors->exists($value)
- || ThrowCodeError('push_invalid_connector');
- return $value;
+ my ($invocant, $value) = @_;
+ $value eq '*'
+ || $value eq 'global'
+ || Bugzilla->push_ext->connectors->exists($value)
+ || ThrowCodeError('push_invalid_connector');
+ return $value;
}
1;
diff --git a/extensions/Push/lib/Push.pm b/extensions/Push/lib/Push.pm
index ab640da81..97bac942b 100644
--- a/extensions/Push/lib/Push.pm
+++ b/extensions/Push/lib/Push.pm
@@ -24,269 +24,273 @@ use Bugzilla::Extension::Push::Util;
use DateTime;
use Try::Tiny;
-has 'is_daemon' => (
- is => 'rw',
- default => 0,
-);
+has 'is_daemon' => (is => 'rw', default => 0,);
sub start {
- my ($self) = @_;
- my $connectors = $self->connectors;
- $self->{config_last_modified} = $self->get_config_last_modified();
- $self->{config_last_checked} = (time);
-
- foreach my $connector ($connectors->list) {
- $connector->backlog->reset_backoff();
- }
-
- my $pushd_loop = IO::Async::Loop->new;
- my $main_timer = IO::Async::Timer::Periodic->new(
- first_interval => 0,
- interval => POLL_INTERVAL_SECONDS,
- reschedule => 'drift',
- on_tick => sub {
- if ( $self->_dbh_check() ) {
- $self->_reload();
- try {
- $self->push();
- }
- catch {
- FATAL($_);
- };
- }
- },
+ my ($self) = @_;
+ my $connectors = $self->connectors;
+ $self->{config_last_modified} = $self->get_config_last_modified();
+ $self->{config_last_checked} = (time);
+
+ foreach my $connector ($connectors->list) {
+ $connector->backlog->reset_backoff();
+ }
+
+ my $pushd_loop = IO::Async::Loop->new;
+ my $main_timer = IO::Async::Timer::Periodic->new(
+ first_interval => 0,
+ interval => POLL_INTERVAL_SECONDS,
+ reschedule => 'drift',
+ on_tick => sub {
+ if ($self->_dbh_check()) {
+ $self->_reload();
+ try {
+ $self->push();
+ }
+ catch {
+ FATAL($_);
+ };
+ }
+ },
+ );
+ if (Bugzilla->datadog) {
+ my $dog_timer = IO::Async::Timer::Periodic->new(
+ interval => 120,
+ reschedule => 'drift',
+ on_tick => sub { $self->heartbeat },
);
- if ( Bugzilla->datadog ) {
- my $dog_timer = IO::Async::Timer::Periodic->new(
- interval => 120,
- reschedule => 'drift',
- on_tick => sub { $self->heartbeat },
- );
- $pushd_loop->add($dog_timer);
- $dog_timer->start;
- }
+ $pushd_loop->add($dog_timer);
+ $dog_timer->start;
+ }
- $pushd_loop->add($main_timer);
- $main_timer->start;
- $pushd_loop->run;
+ $pushd_loop->add($main_timer);
+ $main_timer->start;
+ $pushd_loop->run;
}
sub heartbeat {
- my ($self) = @_;
- my $dd = Bugzilla->datadog('bugzilla.pushd');
-
- $dd->gauge('scheduled_jobs', Bugzilla->dbh->selectrow_array('SELECT COUNT(*) FROM push'));
-
- foreach my $connector ($self->connectors->list) {
- if ($connector->enabled) {
- my $lcname = lc $connector->name;
- $dd->gauge("${lcname}.backlog", Bugzilla->dbh->selectrow_array('SELECT COUNT(*) FROM push_backlog WHERE connector = ?', undef, $connector->name));
- }
+ my ($self) = @_;
+ my $dd = Bugzilla->datadog('bugzilla.pushd');
+
+ $dd->gauge('scheduled_jobs',
+ Bugzilla->dbh->selectrow_array('SELECT COUNT(*) FROM push'));
+
+ foreach my $connector ($self->connectors->list) {
+ if ($connector->enabled) {
+ my $lcname = lc $connector->name;
+ $dd->gauge(
+ "${lcname}.backlog",
+ Bugzilla->dbh->selectrow_array(
+ 'SELECT COUNT(*) FROM push_backlog WHERE connector = ?', undef,
+ $connector->name
+ )
+ );
}
+ }
}
sub push {
- my ($self) = @_;
- my $logger = $self->logger;
- my $connectors = $self->connectors;
+ my ($self) = @_;
+ my $logger = $self->logger;
+ my $connectors = $self->connectors;
+
+ my $enabled = 0;
+ foreach my $connector ($connectors->list) {
+ if ($connector->enabled) {
+ $enabled = 1;
+ last;
+ }
+ }
+ return unless $enabled;
- my $enabled = 0;
+ $logger->debug("polling");
+
+ # process each message
+ while (my $message = $self->queue->oldest) {
foreach my $connector ($connectors->list) {
- if ($connector->enabled) {
- $enabled = 1;
- last;
+ next unless $connector->enabled;
+ next unless $connector->should_send($message);
+ $logger->debug("pushing to " . $connector->name);
+
+ my $is_backlogged = $connector->backlog->count;
+
+ if (!$is_backlogged) {
+
+ # connector isn't backlogged, immediate send
+ $logger->debug("immediate send");
+ my ($result, $data);
+ eval { ($result, $data) = $connector->send($message); };
+ if ($@) {
+ $result = PUSH_RESULT_TRANSIENT;
+ $data = clean_error($@);
}
- }
- return unless $enabled;
-
- $logger->debug("polling");
-
- # process each message
- while(my $message = $self->queue->oldest) {
- foreach my $connector ($connectors->list) {
- next unless $connector->enabled;
- next unless $connector->should_send($message);
- $logger->debug("pushing to " . $connector->name);
-
- my $is_backlogged = $connector->backlog->count;
-
- if (!$is_backlogged) {
- # connector isn't backlogged, immediate send
- $logger->debug("immediate send");
- my ($result, $data);
- eval {
- ($result, $data) = $connector->send($message);
- };
- if ($@) {
- $result = PUSH_RESULT_TRANSIENT;
- $data = clean_error($@);
- }
- if (!$result) {
- $logger->error($connector->name . " failed to return a result code");
- $result = PUSH_RESULT_UNKNOWN;
- }
- $logger->result($connector, $message, $result, $data);
-
- if ($result == PUSH_RESULT_TRANSIENT) {
- $is_backlogged = 1;
- }
- }
-
- # if the connector is backlogged, push to the backlog queue
- if ($is_backlogged) {
- INFO('connector is backlogged');
- my $backlog = Bugzilla::Extension::Push::BacklogMessage->create_from_message($message, $connector);
- }
+ if (!$result) {
+ $logger->error($connector->name . " failed to return a result code");
+ $result = PUSH_RESULT_UNKNOWN;
}
+ $logger->result($connector, $message, $result, $data);
- # message processed
- $message->remove_from_db();
+ if ($result == PUSH_RESULT_TRANSIENT) {
+ $is_backlogged = 1;
+ }
+ }
+
+ # if the connector is backlogged, push to the backlog queue
+ if ($is_backlogged) {
+ INFO('connector is backlogged');
+ my $backlog
+ = Bugzilla::Extension::Push::BacklogMessage->create_from_message($message,
+ $connector);
+ }
}
- # process backlog
- foreach my $connector ($connectors->list) {
- next unless $connector->enabled;
- my $message = $connector->backlog->oldest();
- next unless $message;
-
- $logger->debug("processing backlog for " . $connector->name);
- while ($message) {
- my ($result, $data);
- eval {
- ($result, $data) = $connector->send($message);
- };
- if ($@) {
- $result = PUSH_RESULT_TRANSIENT;
- $data = $@;
- }
- $message->inc_attempts($result == PUSH_RESULT_OK ? '' : $data);
- if (!$result) {
- $logger->error($connector->name . " failed to return a result code");
- $result = PUSH_RESULT_UNKNOWN;
- }
- $logger->result($connector, $message, $result, $data);
-
- if ($result == PUSH_RESULT_TRANSIENT) {
- # connector is still down, stop trying
- $connector->backlog->inc_backoff();
- last;
- }
-
- # message was processed
- $message->remove_from_db();
-
- $message = $connector->backlog->oldest();
- }
+ # message processed
+ $message->remove_from_db();
+ }
+
+ # process backlog
+ foreach my $connector ($connectors->list) {
+ next unless $connector->enabled;
+ my $message = $connector->backlog->oldest();
+ next unless $message;
+
+ $logger->debug("processing backlog for " . $connector->name);
+ while ($message) {
+ my ($result, $data);
+ eval { ($result, $data) = $connector->send($message); };
+ if ($@) {
+ $result = PUSH_RESULT_TRANSIENT;
+ $data = $@;
+ }
+ $message->inc_attempts($result == PUSH_RESULT_OK ? '' : $data);
+ if (!$result) {
+ $logger->error($connector->name . " failed to return a result code");
+ $result = PUSH_RESULT_UNKNOWN;
+ }
+ $logger->result($connector, $message, $result, $data);
+
+ if ($result == PUSH_RESULT_TRANSIENT) {
+
+ # connector is still down, stop trying
+ $connector->backlog->inc_backoff();
+ last;
+ }
+
+ # message was processed
+ $message->remove_from_db();
+
+ $message = $connector->backlog->oldest();
}
+ }
}
sub _reload {
- my ($self) = @_;
-
- # check for updated config every 60 seconds
- my $now = (time);
- if ($now - $self->{config_last_checked} < 60) {
- return;
- }
- $self->{config_last_checked} = $now;
-
- $self->logger->debug('Checking for updated configuration');
- if ($self->get_config_last_modified eq $self->{config_last_modified}) {
- return;
- }
- $self->{config_last_modified} = $self->get_config_last_modified();
-
- $self->logger->debug('Configuration has been updated');
- $self->connectors->reload();
+ my ($self) = @_;
+
+ # check for updated config every 60 seconds
+ my $now = (time);
+ if ($now - $self->{config_last_checked} < 60) {
+ return;
+ }
+ $self->{config_last_checked} = $now;
+
+ $self->logger->debug('Checking for updated configuration');
+ if ($self->get_config_last_modified eq $self->{config_last_modified}) {
+ return;
+ }
+ $self->{config_last_modified} = $self->get_config_last_modified();
+
+ $self->logger->debug('Configuration has been updated');
+ $self->connectors->reload();
}
sub get_config_last_modified {
- my ($self) = @_;
- my $options_list = Bugzilla::Extension::Push::Option->match({
- connector => '*',
- option_name => 'last-modified',
+ my ($self) = @_;
+ my $options_list
+ = Bugzilla::Extension::Push::Option->match({
+ connector => '*', option_name => 'last-modified',
});
- if (@$options_list) {
- return $options_list->[0]->value;
- } else {
- return $self->set_config_last_modified();
- }
+ if (@$options_list) {
+ return $options_list->[0]->value;
+ }
+ else {
+ return $self->set_config_last_modified();
+ }
}
sub set_config_last_modified {
- my ($self) = @_;
- my $options_list = Bugzilla::Extension::Push::Option->match({
- connector => '*',
- option_name => 'last-modified',
+ my ($self) = @_;
+ my $options_list
+ = Bugzilla::Extension::Push::Option->match({
+ connector => '*', option_name => 'last-modified',
});
- my $now = DateTime->now->datetime();
- if (@$options_list) {
- $options_list->[0]->set_value($now);
- $options_list->[0]->update();
- } else {
- Bugzilla::Extension::Push::Option->create({
- connector => '*',
- option_name => 'last-modified',
- option_value => $now,
- });
- }
- return $now;
+ my $now = DateTime->now->datetime();
+ if (@$options_list) {
+ $options_list->[0]->set_value($now);
+ $options_list->[0]->update();
+ }
+ else {
+ Bugzilla::Extension::Push::Option->create({
+ connector => '*', option_name => 'last-modified', option_value => $now,
+ });
+ }
+ return $now;
}
sub config {
- my ($self) = @_;
- if (!$self->{config}) {
- $self->{config} = Bugzilla::Extension::Push::Config->new(
- 'global',
- {
- name => 'log_purge',
- label => 'Purge logs older than (days)',
- type => 'string',
- default => '7',
- required => '1',
- validate => sub { $_[0] =~ /\D/ && die "Invalid purge duration (must be numeric)\n"; },
- },
- );
- $self->{config}->load();
- }
- return $self->{config};
+ my ($self) = @_;
+ if (!$self->{config}) {
+ $self->{config} = Bugzilla::Extension::Push::Config->new(
+ 'global',
+ {
+ name => 'log_purge',
+ label => 'Purge logs older than (days)',
+ type => 'string',
+ default => '7',
+ required => '1',
+ validate =>
+ sub { $_[0] =~ /\D/ && die "Invalid purge duration (must be numeric)\n"; },
+ },
+ );
+ $self->{config}->load();
+ }
+ return $self->{config};
}
sub logger {
- my ($self, $value) = @_;
- $self->{logger} = $value if $value;
- return $self->{logger};
+ my ($self, $value) = @_;
+ $self->{logger} = $value if $value;
+ return $self->{logger};
}
sub connectors {
- my ($self, $value) = @_;
- $self->{connectors} = $value if $value;
- return $self->{connectors};
+ my ($self, $value) = @_;
+ $self->{connectors} = $value if $value;
+ return $self->{connectors};
}
sub queue {
- my ($self) = @_;
- $self->{queue} ||= Bugzilla::Extension::Push::Queue->new();
- return $self->{queue};
+ my ($self) = @_;
+ $self->{queue} ||= Bugzilla::Extension::Push::Queue->new();
+ return $self->{queue};
}
sub log {
- my ($self) = @_;
- $self->{log} ||= Bugzilla::Extension::Push::Log->new();
- return $self->{log};
+ my ($self) = @_;
+ $self->{log} ||= Bugzilla::Extension::Push::Log->new();
+ return $self->{log};
}
sub _dbh_check {
- my ($self) = @_;
- eval {
- Bugzilla->dbh->selectrow_array("SELECT 1 FROM push");
- };
- if ($@) {
- $self->logger->error(clean_error($@));
- return 0;
- } else {
- return 1;
- }
+ my ($self) = @_;
+ eval { Bugzilla->dbh->selectrow_array("SELECT 1 FROM push"); };
+ if ($@) {
+ $self->logger->error(clean_error($@));
+ return 0;
+ }
+ else {
+ return 1;
+ }
}
1;
diff --git a/extensions/Push/lib/Queue.pm b/extensions/Push/lib/Queue.pm
index 3ee0321d9..f59423e6a 100644
--- a/extensions/Push/lib/Queue.pm
+++ b/extensions/Push/lib/Queue.pm
@@ -15,59 +15,54 @@ use Bugzilla;
use Bugzilla::Extension::Push::Message;
sub new {
- my ($class) = @_;
- my $self = {};
- bless($self, $class);
- return $self;
+ my ($class) = @_;
+ my $self = {};
+ bless($self, $class);
+ return $self;
}
sub count {
- my ($self) = @_;
- my $dbh = Bugzilla->dbh;
- return $dbh->selectrow_array("SELECT COUNT(*) FROM push");
+ my ($self) = @_;
+ my $dbh = Bugzilla->dbh;
+ return $dbh->selectrow_array("SELECT COUNT(*) FROM push");
}
sub oldest {
- my ($self) = @_;
- my @messages = $self->list(limit => 1);
- return scalar(@messages) ? $messages[0] : undef;
+ my ($self) = @_;
+ my @messages = $self->list(limit => 1);
+ return scalar(@messages) ? $messages[0] : undef;
}
sub by_id {
- my ($self, $id) = @_;
- my @messages = $self->list(
- limit => 1,
- filter => "AND (push.id = $id)",
- );
- return scalar(@messages) ? $messages[0] : undef;
+ my ($self, $id) = @_;
+ my @messages = $self->list(limit => 1, filter => "AND (push.id = $id)",);
+ return scalar(@messages) ? $messages[0] : undef;
}
sub list {
- my ($self, %args) = @_;
- $args{limit} ||= 10;
- $args{filter} ||= '';
- my @result;
- my $dbh = Bugzilla->dbh;
+ my ($self, %args) = @_;
+ $args{limit} ||= 10;
+ $args{filter} ||= '';
+ my @result;
+ my $dbh = Bugzilla->dbh;
- my $sth = $dbh->prepare("
+ my $sth = $dbh->prepare("
SELECT id, push_ts, payload, change_set, routing_key
FROM push
- WHERE (1 = 1) " .
- $args{filter} . "
- ORDER BY push_ts " .
- $dbh->sql_limit($args{limit})
- );
- $sth->execute();
- while (my $row = $sth->fetchrow_hashref()) {
- push @result, Bugzilla::Extension::Push::Message->new({
- id => $row->{id},
- push_ts => $row->{push_ts},
- payload => $row->{payload},
- change_set => $row->{change_set},
- routing_key => $row->{routing_key},
- });
- }
- return @result;
+ WHERE (1 = 1) " . $args{filter} . "
+ ORDER BY push_ts " . $dbh->sql_limit($args{limit}));
+ $sth->execute();
+ while (my $row = $sth->fetchrow_hashref()) {
+ push @result,
+ Bugzilla::Extension::Push::Message->new({
+ id => $row->{id},
+ push_ts => $row->{push_ts},
+ payload => $row->{payload},
+ change_set => $row->{change_set},
+ routing_key => $row->{routing_key},
+ });
+ }
+ return @result;
}
1;
diff --git a/extensions/Push/lib/Serialise.pm b/extensions/Push/lib/Serialise.pm
index bb6834c13..c878ff4d9 100644
--- a/extensions/Push/lib/Serialise.pm
+++ b/extensions/Push/lib/Serialise.pm
@@ -19,140 +19,145 @@ use Scalar::Util 'blessed';
use JSON ();
my $_instance;
+
sub instance {
- $_instance ||= Bugzilla::Extension::Push::Serialise->_new();
- return $_instance;
+ $_instance ||= Bugzilla::Extension::Push::Serialise->_new();
+ return $_instance;
}
sub _new {
- my ($class) = @_;
- my $self = {};
- bless($self, $class);
- return $self;
+ my ($class) = @_;
+ my $self = {};
+ bless($self, $class);
+ return $self;
}
# given an object, serliase to a hash
sub object_to_hash {
- my ($self, $object, $is_shallow) = @_;
-
- my $method = lc(blessed($object));
- $method =~ s/::/_/g;
- $method =~ s/^bugzilla//;
- return unless $self->can($method);
- (my $name = $method) =~ s/^_//;
-
- # check for a cached hash
- my $cache = Bugzilla->request_cache;
- my $cache_id = "push." . ($is_shallow ? 'shallow.' : 'deep.') . $object;
- if (exists($cache->{$cache_id})) {
- return wantarray ? ($cache->{$cache_id}, $name) : $cache->{$cache_id};
- }
-
- # call the right method to serialise to a hash
- my $rh = $self->$method($object, $is_shallow);
-
- # store in cache
- if ($cache_id) {
- $cache->{$cache_id} = $rh;
- }
-
- return wantarray ? ($rh, $name) : $rh;
+ my ($self, $object, $is_shallow) = @_;
+
+ my $method = lc(blessed($object));
+ $method =~ s/::/_/g;
+ $method =~ s/^bugzilla//;
+ return unless $self->can($method);
+ (my $name = $method) =~ s/^_//;
+
+ # check for a cached hash
+ my $cache = Bugzilla->request_cache;
+ my $cache_id = "push." . ($is_shallow ? 'shallow.' : 'deep.') . $object;
+ if (exists($cache->{$cache_id})) {
+ return wantarray ? ($cache->{$cache_id}, $name) : $cache->{$cache_id};
+ }
+
+ # call the right method to serialise to a hash
+ my $rh = $self->$method($object, $is_shallow);
+
+ # store in cache
+ if ($cache_id) {
+ $cache->{$cache_id} = $rh;
+ }
+
+ return wantarray ? ($rh, $name) : $rh;
}
# given a changes hash, return an event hash
sub changes_to_event {
- my ($self, $changes) = @_;
-
- my $event = {};
-
- # create common (created and modified) fields
- $event->{'user'} = $self->object_to_hash(Bugzilla->user);
- my $timestamp =
- $changes->{'timestamp'}
- || Bugzilla->dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
- $event->{'time'} = datetime_to_timestamp($timestamp);
-
- foreach my $change (@{$changes->{'changes'}}) {
- if (exists $change->{'field'}) {
- # map undef to emtpy
- hash_undef_to_empty($change);
-
- # custom_fields change from undef to empty, ignore these changes
- return if ($change->{'added'} || "") eq "" &&
- ($change->{'removed'} || "") eq "";
-
- # use saner field serialisation
- my $field = $change->{'field'};
- $change->{'field'} = $field;
-
- if ($field eq 'priority' || $field eq 'target_milestone') {
- $change->{'added'} = _select($change->{'added'});
- $change->{'removed'} = _select($change->{'removed'});
-
- } elsif ($field =~ /^cf_/) {
- $change->{'added'} = _custom_field($field, $change->{'added'});
- $change->{'removed'} = _custom_field($field, $change->{'removed'});
- }
-
- $event->{'changes'} = [] unless exists $event->{'changes'};
- push @{$event->{'changes'}}, $change;
- }
+ my ($self, $changes) = @_;
+
+ my $event = {};
+
+ # create common (created and modified) fields
+ $event->{'user'} = $self->object_to_hash(Bugzilla->user);
+ my $timestamp = $changes->{'timestamp'}
+ || Bugzilla->dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)');
+ $event->{'time'} = datetime_to_timestamp($timestamp);
+
+ foreach my $change (@{$changes->{'changes'}}) {
+ if (exists $change->{'field'}) {
+
+ # map undef to emtpy
+ hash_undef_to_empty($change);
+
+ # custom_fields change from undef to empty, ignore these changes
+ return
+ if ($change->{'added'} || "") eq "" && ($change->{'removed'} || "") eq "";
+
+ # use saner field serialisation
+ my $field = $change->{'field'};
+ $change->{'field'} = $field;
+
+ if ($field eq 'priority' || $field eq 'target_milestone') {
+ $change->{'added'} = _select($change->{'added'});
+ $change->{'removed'} = _select($change->{'removed'});
+
+ }
+ elsif ($field =~ /^cf_/) {
+ $change->{'added'} = _custom_field($field, $change->{'added'});
+ $change->{'removed'} = _custom_field($field, $change->{'removed'});
+ }
+
+ $event->{'changes'} = [] unless exists $event->{'changes'};
+ push @{$event->{'changes'}}, $change;
}
+ }
- return $event;
+ return $event;
}
# bugzilla returns '---' or '--' for single-select fields that have no value
# selected. it makes more sense to return an empty string.
sub _select {
- my ($value) = @_;
- return '' if $value eq '---' or $value eq '--';
- return $value;
+ my ($value) = @_;
+ return '' if $value eq '---' or $value eq '--';
+ return $value;
}
# return an object which serialises to a json boolean, but still acts as a perl
# boolean
sub _boolean {
- my ($value) = @_;
- return $value ? JSON::true : JSON::false;
+ my ($value) = @_;
+ return $value ? JSON::true : JSON::false;
}
sub _string {
- my ($value) = @_;
- return defined($value) ? $value : '';
+ my ($value) = @_;
+ return defined($value) ? $value : '';
}
sub _time {
- my ($value) = @_;
- return defined($value) ? datetime_to_timestamp($value) : undef;
+ my ($value) = @_;
+ return defined($value) ? datetime_to_timestamp($value) : undef;
}
sub _integer {
- my ($value) = @_;
- return defined($value) ? $value + 0 : undef;
+ my ($value) = @_;
+ return defined($value) ? $value + 0 : undef;
}
sub _array {
- my ($value) = @_;
- return defined($value) ? $value : [];
+ my ($value) = @_;
+ return defined($value) ? $value : [];
}
sub _custom_field {
- my ($field, $value) = @_;
- $field = Bugzilla::Field->new({ name => $field }) unless blessed $field;
+ my ($field, $value) = @_;
+ $field = Bugzilla::Field->new({name => $field}) unless blessed $field;
- if ($field->type == FIELD_TYPE_DATETIME) {
- return _time($value);
+ if ($field->type == FIELD_TYPE_DATETIME) {
+ return _time($value);
- } elsif ($field->type == FIELD_TYPE_SINGLE_SELECT) {
- return _select($value);
+ }
+ elsif ($field->type == FIELD_TYPE_SINGLE_SELECT) {
+ return _select($value);
- } elsif ($field->type == FIELD_TYPE_MULTI_SELECT) {
- return _array($value);
+ }
+ elsif ($field->type == FIELD_TYPE_MULTI_SELECT) {
+ return _array($value);
- } else {
- return _string($value);
- }
+ }
+ else {
+ return _string($value);
+ }
}
#
@@ -162,158 +167,148 @@ sub _custom_field {
#
sub _bug {
- my ($self, $bug) = @_;
-
- my $version = $bug->can('version_obj')
- ? $bug->version_obj
- : Bugzilla::Version->new({ name => $bug->version, product => $bug->product_obj });
-
- my $milestone;
- if (_select($bug->target_milestone) ne '') {
- $milestone = $bug->can('target_milestone_obj')
- ? $bug->target_milestone_obj
- : Bugzilla::Milestone->new({ name => $bug->target_milestone, product => $bug->product_obj });
- }
-
- my $status = $bug->can('status_obj')
- ? $bug->status_obj
- : Bugzilla::Status->new({ name => $bug->bug_status });
-
- my $rh = {
- id => _integer($bug->bug_id),
- alias => _string($bug->alias),
- assigned_to => $self->_user($bug->assigned_to),
- classification => _string($bug->classification),
- component => $self->_component($bug->component_obj),
- creation_time => _time($bug->creation_ts || $bug->delta_ts),
- flags => (mapr { $self->_flag($_) } $bug->flags),
- is_private => _boolean(!is_public($bug)),
- keywords => (mapr { _string($_->name) } $bug->keyword_objects),
- last_change_time => _time($bug->delta_ts),
- operating_system => _string($bug->op_sys),
- platform => _string($bug->rep_platform),
- priority => _select($bug->priority),
- product => $self->_product($bug->product_obj),
- qa_contact => $self->_user($bug->qa_contact),
- reporter => $self->_user($bug->reporter),
- resolution => _string($bug->resolution),
- severity => _string($bug->bug_severity),
- status => $self->_status($status),
- summary => _string($bug->short_desc),
- target_milestone => $self->_milestone($milestone),
- url => _string($bug->bug_file_loc),
- version => $self->_version($version),
- whiteboard => _string($bug->status_whiteboard),
- };
-
- # add custom fields
- my @custom_fields = Bugzilla->active_custom_fields(
- { product => $bug->product_obj, component => $bug->component_obj });
- foreach my $field (@custom_fields) {
- my $name = $field->name;
- $rh->{$name} = _custom_field($field, $bug->$name);
- }
-
- return $rh;
+ my ($self, $bug) = @_;
+
+ my $version
+ = $bug->can('version_obj')
+ ? $bug->version_obj
+ : Bugzilla::Version->new(
+ {name => $bug->version, product => $bug->product_obj});
+
+ my $milestone;
+ if (_select($bug->target_milestone) ne '') {
+ $milestone
+ = $bug->can('target_milestone_obj')
+ ? $bug->target_milestone_obj
+ : Bugzilla::Milestone->new(
+ {name => $bug->target_milestone, product => $bug->product_obj});
+ }
+
+ my $status
+ = $bug->can('status_obj')
+ ? $bug->status_obj
+ : Bugzilla::Status->new({name => $bug->bug_status});
+
+ my $rh = {
+ id => _integer($bug->bug_id),
+ alias => _string($bug->alias),
+ assigned_to => $self->_user($bug->assigned_to),
+ classification => _string($bug->classification),
+ component => $self->_component($bug->component_obj),
+ creation_time => _time($bug->creation_ts || $bug->delta_ts),
+ flags => (mapr { $self->_flag($_) } $bug->flags),
+ is_private => _boolean(!is_public($bug)),
+ keywords => (mapr { _string($_->name) } $bug->keyword_objects),
+ last_change_time => _time($bug->delta_ts),
+ operating_system => _string($bug->op_sys),
+ platform => _string($bug->rep_platform),
+ priority => _select($bug->priority),
+ product => $self->_product($bug->product_obj),
+ qa_contact => $self->_user($bug->qa_contact),
+ reporter => $self->_user($bug->reporter),
+ resolution => _string($bug->resolution),
+ severity => _string($bug->bug_severity),
+ status => $self->_status($status),
+ summary => _string($bug->short_desc),
+ target_milestone => $self->_milestone($milestone),
+ url => _string($bug->bug_file_loc),
+ version => $self->_version($version),
+ whiteboard => _string($bug->status_whiteboard),
+ };
+
+ # add custom fields
+ my @custom_fields = Bugzilla->active_custom_fields(
+ {product => $bug->product_obj, component => $bug->component_obj});
+ foreach my $field (@custom_fields) {
+ my $name = $field->name;
+ $rh->{$name} = _custom_field($field, $bug->$name);
+ }
+
+ return $rh;
}
sub _user {
- my ($self, $user) = @_;
- return undef unless $user;
- return {
- id => _integer($user->id),
- login => _string($user->login),
- real_name => _string($user->name),
- };
+ my ($self, $user) = @_;
+ return undef unless $user;
+ return {
+ id => _integer($user->id),
+ login => _string($user->login),
+ real_name => _string($user->name),
+ };
}
sub _component {
- my ($self, $component) = @_;
- return {
- id => _integer($component->id),
- name => _string($component->name),
- };
+ my ($self, $component) = @_;
+ return {id => _integer($component->id), name => _string($component->name),};
}
sub _attachment {
- my ($self, $attachment, $is_shallow) = @_;
- my $rh = {
- id => _integer($attachment->id),
- content_type => _string($attachment->contenttype),
- creation_time => _time($attachment->attached),
- description => _string($attachment->description),
- file_name => _string($attachment->filename),
- flags => (mapr { $self->_flag($_) } $attachment->flags),
- is_obsolete => _boolean($attachment->isobsolete),
- is_patch => _boolean($attachment->ispatch),
- is_private => _boolean(!is_public($attachment)),
- last_change_time => _time($attachment->modification_time),
- };
- if (!$is_shallow) {
- $rh->{bug} = $self->_bug($attachment->bug);
- }
- return $rh;
+ my ($self, $attachment, $is_shallow) = @_;
+ my $rh = {
+ id => _integer($attachment->id),
+ content_type => _string($attachment->contenttype),
+ creation_time => _time($attachment->attached),
+ description => _string($attachment->description),
+ file_name => _string($attachment->filename),
+ flags => (mapr { $self->_flag($_) } $attachment->flags),
+ is_obsolete => _boolean($attachment->isobsolete),
+ is_patch => _boolean($attachment->ispatch),
+ is_private => _boolean(!is_public($attachment)),
+ last_change_time => _time($attachment->modification_time),
+ };
+ if (!$is_shallow) {
+ $rh->{bug} = $self->_bug($attachment->bug);
+ }
+ return $rh;
}
sub _comment {
- my ($self, $comment, $is_shallow) = @_;
- my $rh = {
- id => _integer($comment->bug_id),
- body => _string($comment->body),
- creation_time => _time($comment->creation_ts),
- is_private => _boolean($comment->is_private),
- number => _integer($comment->count),
- };
- if (!$is_shallow) {
- $rh->{bug} = $self->_bug($comment->bug);
- }
- return $rh;
+ my ($self, $comment, $is_shallow) = @_;
+ my $rh = {
+ id => _integer($comment->bug_id),
+ body => _string($comment->body),
+ creation_time => _time($comment->creation_ts),
+ is_private => _boolean($comment->is_private),
+ number => _integer($comment->count),
+ };
+ if (!$is_shallow) {
+ $rh->{bug} = $self->_bug($comment->bug);
+ }
+ return $rh;
}
sub _product {
- my ($self, $product) = @_;
- return {
- id => _integer($product->id),
- name => _string($product->name),
- };
+ my ($self, $product) = @_;
+ return {id => _integer($product->id), name => _string($product->name),};
}
sub _flag {
- my ($self, $flag) = @_;
- my $rh = {
- id => _integer($flag->id),
- name => _string($flag->type->name),
- value => _string($flag->status),
- };
- if ($flag->requestee) {
- $rh->{'requestee'} = $self->_user($flag->requestee);
- }
- return $rh;
+ my ($self, $flag) = @_;
+ my $rh = {
+ id => _integer($flag->id),
+ name => _string($flag->type->name),
+ value => _string($flag->status),
+ };
+ if ($flag->requestee) {
+ $rh->{'requestee'} = $self->_user($flag->requestee);
+ }
+ return $rh;
}
sub _version {
- my ($self, $version) = @_;
- return {
- id => _integer($version->id),
- name => _string($version->name),
- };
+ my ($self, $version) = @_;
+ return {id => _integer($version->id), name => _string($version->name),};
}
sub _milestone {
- my ($self, $milestone) = @_;
- return undef unless $milestone;
- return {
- id => _integer($milestone->id),
- name => _string($milestone->name),
- };
+ my ($self, $milestone) = @_;
+ return undef unless $milestone;
+ return {id => _integer($milestone->id), name => _string($milestone->name),};
}
sub _status {
- my ($self, $status) = @_;
- return {
- id => _integer($status->id),
- name => _string($status->name),
- };
+ my ($self, $status) = @_;
+ return {id => _integer($status->id), name => _string($status->name),};
}
1;
diff --git a/extensions/Push/lib/Util.pm b/extensions/Push/lib/Util.pm
index bda6331bf..34a0879ea 100644
--- a/extensions/Push/lib/Util.pm
+++ b/extensions/Push/lib/Util.pm
@@ -22,142 +22,147 @@ use Time::HiRes;
use base qw(Exporter);
our @EXPORT = qw(
- datetime_to_timestamp
- debug_dump
- get_first_value
- hash_undef_to_empty
- is_public
- mapr
- clean_error
- change_set_id
- canon_email
- to_json from_json
+ datetime_to_timestamp
+ debug_dump
+ get_first_value
+ hash_undef_to_empty
+ is_public
+ mapr
+ clean_error
+ change_set_id
+ canon_email
+ to_json from_json
);
# returns true if the specified object is public
sub is_public {
- my ($object) = @_;
+ my ($object) = @_;
- my $default_user = Bugzilla::User->new();
+ my $default_user = Bugzilla::User->new();
- if ($object->isa('Bugzilla::Bug')) {
- return unless $default_user->can_see_bug($object->bug_id);
- return 1;
+ if ($object->isa('Bugzilla::Bug')) {
+ return unless $default_user->can_see_bug($object->bug_id);
+ return 1;
- } elsif ($object->isa('Bugzilla::Comment')) {
- return if $object->is_private;
- return unless $default_user->can_see_bug($object->bug_id);
- return 1;
+ }
+ elsif ($object->isa('Bugzilla::Comment')) {
+ return if $object->is_private;
+ return unless $default_user->can_see_bug($object->bug_id);
+ return 1;
- } elsif ($object->isa('Bugzilla::Attachment')) {
- return if $object->isprivate;
- return unless $default_user->can_see_bug($object->bug_id);
- return 1;
+ }
+ elsif ($object->isa('Bugzilla::Attachment')) {
+ return if $object->isprivate;
+ return unless $default_user->can_see_bug($object->bug_id);
+ return 1;
- } else {
- warn "Unsupported class " . blessed($object) . " passed to is_public()\n";
- }
+ }
+ else {
+ warn "Unsupported class " . blessed($object) . " passed to is_public()\n";
+ }
- return 1;
+ return 1;
}
# return the first existing value from the hashref for the given list of keys
sub get_first_value {
- my ($rh, @keys) = @_;
- foreach my $field (@keys) {
- return $rh->{$field} if exists $rh->{$field};
- }
- return;
+ my ($rh, @keys) = @_;
+ foreach my $field (@keys) {
+ return $rh->{$field} if exists $rh->{$field};
+ }
+ return;
}
# wrapper for map that works on array references
sub mapr(&$) {
- my ($filter, $ra) = @_;
- my @result = map(&$filter, @$ra);
- return \@result;
+ my ($filter, $ra) = @_;
+ my @result = map(&$filter, @$ra);
+ return \@result;
}
# convert datetime string (from db) to a UTC json friendly datetime
sub datetime_to_timestamp {
- my ($datetime_string) = @_;
- return '' unless $datetime_string;
- return datetime_from($datetime_string, 'UTC')->datetime();
+ my ($datetime_string) = @_;
+ return '' unless $datetime_string;
+ return datetime_from($datetime_string, 'UTC')->datetime();
}
# replaces all undef values in a hashref with an empty string (deep)
sub hash_undef_to_empty {
- my ($rh) = @_;
- foreach my $key (keys %$rh) {
- my $value = $rh->{$key};
- if (!defined($value)) {
- $rh->{$key} = '';
- } elsif (ref($value) eq 'HASH') {
- hash_undef_to_empty($value);
- }
+ my ($rh) = @_;
+ foreach my $key (keys %$rh) {
+ my $value = $rh->{$key};
+ if (!defined($value)) {
+ $rh->{$key} = '';
+ }
+ elsif (ref($value) eq 'HASH') {
+ hash_undef_to_empty($value);
}
+ }
}
# debugging methods
sub debug_dump {
- my ($object) = @_;
- local $Data::Dumper::Sortkeys = 1;
- my $output = Dumper($object);
- $output =~ s/</&lt;/g;
- print "<pre>$output</pre>";
+ my ($object) = @_;
+ local $Data::Dumper::Sortkeys = 1;
+ my $output = Dumper($object);
+ $output =~ s/</&lt;/g;
+ print "<pre>$output</pre>";
}
# removes stacktrace and "at /some/path ..." from errors
sub clean_error {
- my ($error) = @_;
- my $path = bz_locations->{'extensionsdir'};
- $error = $1 if $error =~ /^(.+?) at \Q$path/s;
- $path = '/loader/0x';
- $error = $1 if $error =~ /^(.+?) at \Q$path/s;
- $error =~ s/(^\s+|\s+$)//g;
- return $error;
+ my ($error) = @_;
+ my $path = bz_locations->{'extensionsdir'};
+ $error = $1 if $error =~ /^(.+?) at \Q$path/s;
+ $path = '/loader/0x';
+ $error = $1 if $error =~ /^(.+?) at \Q$path/s;
+ $error =~ s/(^\s+|\s+$)//g;
+ return $error;
}
# generate a new change_set id
sub change_set_id {
- return "$$." . Time::HiRes::time();
+ return "$$." . Time::HiRes::time();
}
# remove guff from email addresses
sub clean_email {
- my $email = shift;
- $email = trim($email);
- $email = $1 if $email =~ /^(\S+)/;
- $email =~ s/&#64;/@/;
- $email = lc $email;
- return $email;
+ my $email = shift;
+ $email = trim($email);
+ $email = $1 if $email =~ /^(\S+)/;
+ $email =~ s/&#64;/@/;
+ $email = lc $email;
+ return $email;
}
# resolve to canonised email form
# eg. glob+bmo@mozilla.com --> glob@mozilla.com
sub canon_email {
- my $email = shift;
- $email = clean_email($email);
- $email =~ s/^([^\+]+)\+[^\@]+(\@.+)$/$1$2/;
- return $email;
+ my $email = shift;
+ $email = clean_email($email);
+ $email =~ s/^([^\+]+)\+[^\@]+(\@.+)$/$1$2/;
+ return $email;
}
# json helpers
sub to_json {
- my ($object, $pretty) = @_;
- if ($pretty) {
- return decode('utf8', JSON->new->utf8(1)->pretty(1)->encode($object));
- } else {
- return JSON->new->ascii(1)->shrink(1)->encode($object);
- }
+ my ($object, $pretty) = @_;
+ if ($pretty) {
+ return decode('utf8', JSON->new->utf8(1)->pretty(1)->encode($object));
+ }
+ else {
+ return JSON->new->ascii(1)->shrink(1)->encode($object);
+ }
}
sub from_json {
- my ($json) = @_;
- if (utf8::is_utf8($json)) {
- $json = encode('utf8', $json);
- }
- return JSON->new->utf8(1)->decode($json);
+ my ($json) = @_;
+ if (utf8::is_utf8($json)) {
+ $json = encode('utf8', $json);
+ }
+ return JSON->new->utf8(1)->decode($json);
}
1;
diff --git a/extensions/Push/template/en/default/setup/strings.txt.pl b/extensions/Push/template/en/default/setup/strings.txt.pl
index 6f41f26d5..7bdab77bd 100644
--- a/extensions/Push/template/en/default/setup/strings.txt.pl
+++ b/extensions/Push/template/en/default/setup/strings.txt.pl
@@ -10,6 +10,6 @@ use warnings;
use 5.10.1;
%strings = (
- feature_push_amqp => 'Push: AMQP Support',
- feature_push_stomp => 'Push: STOMP Support',
+ feature_push_amqp => 'Push: AMQP Support',
+ feature_push_stomp => 'Push: STOMP Support',
);