API-MikroTik
view release on metacpan or search on metacpan
lib/API/MikroTik.pm view on Meta::CPAN
=head2 command
my $command = '/interface/print';
my $attr = {'.proplist' => '.id,name,type'};
my $query = {type => ['ipip-tunnel', 'gre-tunnel'], running => 'true'};
my $list = $api->command($command, $attr, $query);
die $api->error if $api->error;
for (@$list) {...}
$api->command('/user/set', {'.id' => 'admin', comment => 'System admin'});
# Non-blocking
$api->command('/ip/address/print' => sub {
my ($api, $err, $list) = @_;
return if $err;
for (@$list) {...}
});
lib/API/MikroTik.pm view on Meta::CPAN
Mojo::IOLoop->timer(
3 => sub { $api->cancel($tag) }
);
Subscribe to an output of commands with continuous responses such as C<listen> or
C<ping>. Should be terminated with L</cancel>.
=head1 DEBUGGING
You can set the API_MIKROTIK_DEBUG environment variable to get some debug output
printed to stderr.
Also, you can change connection timeout with the API_MIKROTIK_CONNTIMEOUT variable.
=head1 COPYRIGHT AND LICENSE
Andre Parker, 2017-2018.
This program is free software, you can redistribute it and/or modify it under
the terms of the Artistic License version 2.0.
lib/API/MikroTik/Query.pm view on Meta::CPAN
# = ['?type=ipip-tunnel', '?type=gre-tunnel', '?#|', '?running=true', '?#&'];
my $query
= build_query({type => ['ipip-tunnel', 'gre-tunnel'], running => 'true'});
Builds a query and returns an arrayref with API query words.
=head1 QUERY SYNTAX
Basic idea is that everything in arrayrefs are C<OR>'ed and everything in hashrefs
are C<AND>'ed unless specified otherwise. Another thing is, where a C<value> is
expected, you should be able to use a list to compare against a set of values.
=head2 Key-value pairs
# type = 'gre-tunnel' AND running = 'true'
my $query = {type => 'gre-tunnel', running => 'true'};
# disabled = 'true' OR running = 'false'
$query = [disabled => 'true', running => 'false'];
Simple attribute value comparison.
lib/API/MikroTik/Sentence.pm view on Meta::CPAN
else { $words = $self->{words} = [] }
while (my $w = $self->_fetch_word($buff)) { push @$words, $w }
return $words;
}
sub is_incomplete {
return exists $_[0]->{_buff};
}
sub reset {
delete @{$_[0]}{qw(words _buff)};
return $_[0];
}
sub _encode_length {
my $len = shift;
my $packed;
# Screw you, mikrotik engineers, just pack length as 4 bytes. >_<
lib/API/MikroTik/Sentence.pm view on Meta::CPAN
with the one stored from a previous call.
=head2 is_incomplete
my $done = !$sentence->is_incomplete;
Indicates that a processed buffer was incomplete and remaining amount of data was
insufficient to complete a sentence.
=head2 reset
my $sentence->reset;
Clears an incomplete status and removes a remaining buffer.
=head1 SEE ALSO
L<API::MikroTik>
=cut
t/mikrotik.t view on Meta::CPAN
use Mojo::IOLoop;
use Mojo::Util qw(steady_time);
# blocking
my $loop = Mojo::IOLoop->new();
my $mockup = API::MikroTik::Mockup->new()->ioloop($loop);
my $port = $loop->acceptor($mockup->server)->port;
my $api = API::MikroTik->new(
user => 'test',
password => 'tset',
host => '127.0.0.1',
port => $port,
tls => 1,
ioloop => $loop,
);
# check connection
$api->tls(1);
my $res = $api->cmd('/resp');
like $api->error, qr/IO::Socket::SSL/, 'connection error';
$api->tls(0);
# check login
$api->password('');
$res = $api->cmd('/resp');
like $api->error, qr/cannot log/, 'login error';
$api->password('tset');
# timeouts
$api->timeout(1);
my $ctime = steady_time();
$res = $api->cmd('/nocmd');
ok((steady_time() - $ctime) < 1.1, 'timeout ok');
$api->timeout(0.5);
$ctime = steady_time();
$res = $api->cmd('/nocmd');
ok((steady_time() - $ctime) < 0.6, 'timeout ok');
use Mojo::Base -strict;
use Test::More;
plan skip_all => 'set TEST_POD to enable this test (developer only!)'
unless $ENV{TEST_POD};
plan skip_all => 'Test::Pod 1.14+ required for this test!'
unless eval 'use Test::Pod 1.14; 1';
all_pod_files_ok();
t/pod_coverage.t view on Meta::CPAN
use Mojo::Base -strict;
use Test::More;
plan skip_all => 'set TEST_POD to enable this test (developer only!)'
unless $ENV{TEST_POD};
plan skip_all => 'Test::Pod::Coverage 1.04+ required for this test!'
unless eval 'use Test::Pod::Coverage 1.04; 1';
# DEPRECATED!
all_pod_coverage_ok({also_private => ['data', 'remaining']});
t/promises.t view on Meta::CPAN
use Mojo::IOLoop;
use Test::More;
plan skip_all => 'Mojolicious v7.54+ required for this test.'
unless API::MikroTik->PROMISES;
my $mockup = API::MikroTik::Mockup->new();
my $port = Mojo::IOLoop->acceptor($mockup->server)->port;
my $api = API::MikroTik->new(
user => 'test',
password => 'tset',
host => '127.0.0.1',
port => $port,
tls => 1,
);
my $p = $api->cmd_p('/resp');
isa_ok $p, 'Mojo::Promise', 'right result type';
# connection errors
my ($err, $res);
t/response.t view on Meta::CPAN
$packed = encode_sentence('!re', $attr);
$packed .= $packed . $packed . $packed;
push @parts, (substr $packed, 0, $_, '') for (900, 700, 880, 820);
$attr->{'.tag'} = '';
$attr->{'.type'} = '!re';
my $w = $r->parse(\$parts[0]);
is_deeply $w, [$attr], 'right result';
ok $r->sentence->is_incomplete, 'incomplete is set';
$w = $r->parse(\$parts[1]);
is_deeply $w, [], 'right result';
ok $r->sentence->is_incomplete, 'incomplete is set';
$w = $r->parse(\$parts[2]);
is_deeply $w, [($attr) x 2], 'right result';
ok $r->sentence->is_incomplete, 'incomplete is set';
$w = $r->parse(\$parts[3]);
is_deeply $w, [$attr], 'right result';
ok !$r->sentence->is_incomplete, 'incomplete is not set';
done_testing();
t/sentence.t view on Meta::CPAN
$words = $s->fetch(\$packed);
is shift @$words, '/cmd/2', 'right command';
is_deeply [sort @$words], ['.tag=11', '=c=foo', '=d=bar', '?e=baz'],
'right attributes';
# buffer ends in the middle of a word
$packed = encode_sentence('/one/two/three', {test => 1, another => 2});
substr $packed, 20, 20, '';
$words = $s->fetch(\$packed);
is_deeply $words, ['/one/two/three'], 'right results';
ok $s->is_incomplete, 'incomplete is set';
# reset
$s->reset;
ok !$s->is_incomplete, 'incomplete is not longer set';
# buffer ends at the end of the word, before an empty closing word
$packed = encode_sentence('/one/two', {three => 'four'});
my $tr = substr $packed, -1, 1, '';
is $tr, "\0", 'trailing empty word';
$words = $s->fetch(\$packed);
is_deeply $words, ['/one/two', '=three=four'], 'right results';
ok $s->is_incomplete, 'incomplete is set';
my $err;
$SIG{__WARN__} = sub { $err = $_[0] };
$packed = encode_sentence('/cmd', {argv => undef});
ok !$err, 'no warning';
$words = $s->reset->fetch(\$packed);
is_deeply $words, ['/cmd', '=argv='], 'right results';
done_testing();
( run in 0.809 second using v1.01-cache-2.11-cpan-49f99fa48dc )