This file is indexed.

/usr/share/perl5/Zabbix/API/CRUDE.pm is in libzabbix-api-perl 0.009-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
package Zabbix::API::CRUDE;

use strict;
use warnings;
use 5.010;
use Carp;

sub new {

    my ($class, %args) = @_;

    my $self = \%args;

    bless $self, $class;

    return $self;

}

sub id {

    croak 'Class '.(ref shift).' does not implement required mutator id()';

}

sub node_id {

    my ($self, $value) = @_;
    
    if (defined $value) {

        croak 'Accessor node_id() called as mutator';

    }

    return unless $self->id;
    return unless $self->id > 100000000000000;
    # this is how Zabbix operates, don't blame me
    return int($self->id/100000000000000);

}

sub prefix {

    croak 'Class '.(ref shift).' does not implement required method prefix()';

}

sub extension {

    croak 'Class '.(ref shift).' does not implement required method extension()';

}

sub name {

    croak 'Class '.(ref shift).' does not implement required method name()';

}

sub data {

    ## accessor for data

    my ($self, $value) = @_;

    if (defined $value) {

        croak 'Accessor data() called as mutator';

    } else {

        $self->{data} = {} unless exists $self->{data};

        return $self->{data};

    }

}

sub pull {

    my ($self, $data) = @_;

    if (defined $data) {

        $self->{data} = $data;

    } else {

        croak sprintf('Cannot pull data from server into a %s without ID', $self->prefix)
            unless $self->id;

        $self->{data} = $self->{root}->query(method => $self->prefix('.get'),
                                             params => {
                                                 $self->prefix('ids') => [ $self->id ],
                                                 $self->extension
                                             })->[0];

    }

    return $self;

}

sub created {

    my $self = shift;

    return $self->id if $self->{root}->{lazy};

    return @{$self->{root}->query(method => $self->prefix('.get'),
                                  params => {
                                      $self->prefix('ids') => [$self->id],
                                      $self->extension
                                  })};

}

sub collides {

    croak 'Class '.(ref shift).' does not implement required method collides()';

}

sub push {

    my ($self, $data) = @_;

    $data //= $self->data;

    my @colliders;

    if ($self->id and $self->created) {

        say sprintf('Updating %s %s', $self->prefix, $self->id)
            if $self->{root}->{verbosity};

        $self->{root}->query(method => $self->prefix('.update'),
                             params => $data);

        $self->pull unless $self->{root}->{lazy};

    } elsif ($self->id) {

        croak sprintf('%s has a %s but does not exist on server', $self->id, $self->prefix('id'));

    } elsif (@colliders = $self->collides and $colliders[0]) {

        say sprintf('Updating %s (match by collisions)', $self->prefix)
            if $self->{root}->{verbosity};

        if (@colliders > 1) {

            croak sprintf('Cannot push %s: too many possible targets', $self->prefix);

        }

        my $class = ref $self;

        # not referenced! and that's the way we want it
        my $collider = $class->new(root => $self->{root}, data => $colliders[0]);

        $self->id($collider->id);

        $self->push;

    } else {

        say 'Creating '.$self->prefix
            if $self->{root}->{verbosity};

        my $id = $self->{root}->query(method => $self->prefix('.create'),
                                      params => $data)->{$self->prefix('ids')}->[0];

        $self->id($id);

        $self->pull unless $self->{root}->{lazy};

    }

    return $self;

}

sub delete {

    my $self = shift;

    if ($self->id) {

        say sprintf('Deleting %s %s', $self->prefix, $self->id)
            if $self->{root}->{verbosity};

        $self->{root}->query(method => $self->prefix('.delete'),
                             params => [ $self->id ]);

    } else {

        carp sprintf(q{Useless call of delete() on a %s that does not have a %s}, $self->prefix, $self->prefix('id'));

    }

    return $self;

}

1;
__END__
=pod

=head1 NAME

Zabbix::API::CRUDE -- Base abstract class for most Zabbix::API::* objects

=head1 SYNOPSIS

  package Zabbix::API::Unicorn;

  use parent qw/Zabbix::API::CRUDE/;

  # now override some virtual methods so that it works for the specific case of
  # unicorns

  sub id { ... }
  sub prefix { ... }
  sub extension { ... }

=head1 DESCRIPTION

This module handles most aspects of pushing, pulling and deleting the various
types of Zabbix objects.  You do not want to use this directly; a few abstract
methods need to be implemented by a subclass.

=head2 WHY "CRUDE"?

=over 4

=item 1

On top of Create, Read, Update and Delete, the Zabbix API also implements an
Exists operation.

=item 2

It I<was> written in a hurry.

=back

=head1 METHODS

=over 4

=item new([DATA]) (constructor)

This is the standard, boilerplate Perl OO constructor.  It returns a blessed
hashref with the contents of C<DATA>, which should be a hash.

=item id([NEWID]) (abstract method)

This method must implement a mutator for the relevant unique Zabbix ID (e.g. for
hosts, C<hostid>).  What this means is, it must accept zero or one argument; if
zero, return the current ID or undef; if one, set the current ID in the raw data
hash (see the C<data()> method) and return it.

=item node_id()

This method returns the current object's node ID, for distributed
setups.  For objects in non-distributed setups, whose IDs do not
include a node ID, and objects that have never been pushed to the
server, this method will return false.

=item prefix([SUFFIX]) (abstract method)

This method must return a string that corresponds to its type (e.g. C<host>).
It should accept one optional argument to concatenate to the type; this kludge
is necessary for types that have a different name depending on where they are
used (e.g. graph items -- not currently implemented as such -- have a
C<graphitemid> but are referred to as C<gitems> elsewhere).

This is a class and instance method (and it returns the same thing in both cases
so far).  Warning: do not rely too much on this returning the correct compound
name for any SUFFIX, as I have implemented only those special cases that were of
interest for the rest of the distribution.

=item extension() (abstract method)

This method must return a list that contains the various parameters necessary to
fetch more data.  (Returning an empty hash means that in most cases, only the
IDs will be sent by the server.)  E.g. for hosts, this is C<< return (output =>
'extend') >>.

=item name() (abstract method)

This method must return a preferably unique human-readable identifier.  For
instance, hosts return the C<host> attribute.

=item data()

This is a standard accessor for the raw data as fetched from Zabbix and
converted into a hashref.  You can use C<pull()> as a mutator on the same (but
not for long).

=item pull([DATA])

Without an argument, fetches the raw data from the Zabbix server and updates the
Perl object appropriately.  Calling C<pull> on objects that do not have an ID
set (they have not been fetched from the server, have never been pushed, or you
have removed the ID yourself for obscure reasons) throws an exception.

With a hashref argument, sets the raw data on the object directly, although this
will change in a future version.

In any case, this does not save your modifications for you.  If you have changed
the object's data in any way and not pushed the modifications to the server,
they will be overwritten.

=item created()

This checks that the server knows about the object (has an object of the same
type with the same ID).

=item collides() (abstract method)

This method must return a list of objects (hashrefs of data, not instances of
C<Zabbix::API>!)  that would cause the Zabbix server to reply "... already
exists" if the invocant were created (as with a push).

=item push()

Create the object on the server if it doesn't exist, update it if it does.  This
distinction means that an object which has an ID, but not a server
representation, is in an illegal state; calling C<push> on such an object throws
an exception.  Some classes (e.g. C<Screen>) override this to ensure that other
objects they depend on are created before they are.

=item delete()

Deletes the object on the server and the local index (if you fetch it again it
will be a different object from the one you're "holding").

=back

=head1 SEE ALSO

L<Zabbix::API>, the Zabbix API documentation at
L<http://www.zabbix.com/documentation/start>.

=head1 AUTHOR

Fabrice Gabolde <fabrice.gabolde@uperto.com>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2011 SFR

This library is free software; you can redistribute it and/or modify it under
the terms of the GPLv3.

=cut