Zabbix7-API/lib/Zabbix7/API/Macro.pm
package Zabbix7::API::Macro;
use strict;
use warnings;
use 5.010;
use Carp;
use autodie;
use utf8;
use Moo;
use JSON;
extends qw/Zabbix7::API::CRUDE/;
sub id {
my ($self, $value) = @_;
if (defined $value) {
if ($self->globalp) {
$self->data->{globalmacroid} = $value;
delete $self->data->{hostmacroid};
Log::Any->get_logger->debug("Set globalmacroid: $value for global macro");
return $self->data->{globalmacroid};
} else {
$self->data->{hostmacroid} = $value;
delete $self->data->{globalmacroid};
Log::Any->get_logger->debug("Set hostmacroid: $value for host macro");
return $self->data->{hostmacroid};
}
}
my $id = $self->globalp ? $self->data->{globalmacroid} : $self->data->{hostmacroid};
Log::Any->get_logger->debug("Retrieved ID for macro: " . ($id // 'none') . ", global: " . ($self->globalp ? 'yes' : 'no'));
return $id;
}
sub _readonly_properties {
return {
hosts => 1,
globalmacroid => 1, # Added for Zabbix 7.0 (read-only for updates)
hostmacroid => 1, # Added for Zabbix 7.0 (read-only for updates)
};
}
sub _prefix {
my ($self, $suffix) = @_;
if ($suffix) {
if ($suffix =~ m/ids?/) {
return ($self->globalp ? 'globalmacro' : 'hostmacro') . $suffix;
} elsif ($suffix eq '.delete') {
return 'usermacro.' . ($self->globalp ? 'deleteglobal' : 'delete');
} elsif ($suffix eq '.create') {
return 'usermacro.' . ($self->globalp ? 'createglobal' : 'create');
} elsif ($suffix eq '.update') {
return 'usermacro.' . ($self->globalp ? 'updateglobal' : 'update');
}
return 'usermacro' . $suffix;
}
return 'usermacro';
}
sub _extension {
return (
output => 'extend',
selectHosts => ['hostid', 'host'], # Added for Zabbix 7.0 (for host macros)
);
}
sub name {
my $self = shift;
my $name = $self->data->{macro} || '???';
Log::Any->get_logger->debug("Retrieved name for macro ID: " . ($self->id // 'new') . ": $name");
return $name;
}
sub value {
my ($self, $value) = @_;
if (defined $value) {
$self->data->{value} = $value;
Log::Any->get_logger->debug("Set value for macro ID: " . ($self->id // 'new') . ": $value");
}
my $val = $self->data->{value};
Log::Any->get_logger->debug("Retrieved value for macro ID: " . ($self->id // 'new') . ": " . ($val // 'none'));
return $val;
}
sub globalp {
my $self = shift;
my $is_global = !exists($self->data->{hostid});
Log::Any->get_logger->debug("Checked globalp for macro ID: " . ($self->id // 'new') . ": " . ($is_global ? 'global' : 'host'));
return $is_global;
}
sub pull {
my $self = shift;
croak(sprintf(q{Cannot pull data from server into a %s without ID}, $self->short_class))
unless $self->id;
my $data = $self->root->query(
method => $self->_prefix('.get'),
params => {
$self->_prefix('ids') => [ $self->id ],
globalmacro => $self->globalp ? JSON::true : JSON::false,
$self->_extension
}
)->[0];
croak(sprintf(q{%s class object has a local ID that does not appear to exist on the server},
$self->short_class)) unless $data;
$self->_set_data($data);
Log::Any->get_logger->debug("Pulled data for $self->short_class ID: " . $self->id);
return $self;
}
sub exists {
my $self = shift;
my $response = $self->root->query(
method => $self->_prefix('.get'),
params => {
$self->_prefix('ids') => [ $self->id ],
globalmacro => $self->globalp ? JSON::true : JSON::false,
countOutput => 1,
}
);
Log::Any->get_logger->debug("Checked existence of $self->short_class ID: " . ($self->id // 'none') . ", exists: $response");
return !!$response;
}
before 'create' => sub {
my ($self) = @_;
delete $self->data->{globalmacroid}; # Ensure IDs are not sent
delete $self->data->{hostmacroid};
Log::Any->get_logger->debug("Preparing to create macro: " . ($self->data->{macro} // 'unknown') . ", global: " . ($self->globalp ? 'yes' : 'no'));
};
before 'update' => sub {
my ($self) = @_;
delete $self->data->{globalmacroid}; # Ensure IDs are not sent
delete $self->data->{hostmacroid};
Log::Any->get_logger->debug("Preparing to update macro ID: " . ($self->id // 'new') . ", global: " . ($self->globalp ? 'yes' : 'no'));
};
1;
__END__
=pod
=head1 NAME
Zabbix7::API::Macro -- Zabbix usermacro objects
=head1 SYNOPSIS
# create a new global macro (set its hostid attribute if you need a
# host macro instead)
my $macro = Zabbix7::API::Macro->new(root => $zabber,
data => { macro => '{$SUPERMACRO}',
value => 'ITSABIRD' });
$macro->create;
# change its value
$macro->value('ITSAPLANE');
$macro->update;
=head1 DESCRIPTION
Handles CRUD for Zabbix usermacro objects.
Both global and host macro types are represented by this class. If
the C<hostid> attribute is undef or empty, then we assume it's a
global macro.
This class' methods work transparently around the weird Zabbix macro
API, which uses different methods on the same object depending on
whether it's a global or host macro... except sometimes, for instance
the C<usermacro.get> method which can be called on both and will
return different keys... And macros don't seem to have an C<exists>
method. It's kind of a mess.
=head1 METHODS
=head2 _prefix
This class' C<_prefix> method is B<not> a class method. The _prefix
returned depends on the type of macro (global or host) which is a
characteristic of an instance.
=head2 globalp
say $macro->globalp ? 'a global macro' : 'a host macro';
Returns a true value when the macro is global, a false value
otherwise.
=head2 name
say $macro->name;
Returns the macro's name, which is also how it's referred to in
expressions, e.g. "{$SUPERMACRO}".
=head2 value
$macro->value('new value');
say $macro->value;
Mutator for the macro's value.
=head1 SEE ALSO
L<Zabbix7::API::CRUDE>
=head1 AUTHOR
SCOTTH
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2011, 2012, 2013, 2014 SFR
Copyright (C) 2020 Fabrice Gabolde
Copyright (C) 2025 ScottH
This library is free software; you can redistribute it and/or modify it under
the terms of the GPLv3.
=cut