Object-Oriented Perl API at CPAN

Hi,

I reworked the existing perl API implementation from cheesegrits and some other guys (see http://forum.mikrotik.com/t/perl-api-client/19990/1) and ported it to Moose.

It will available at CPAN: http://search.cpan.org/~martingo/MikroTik-API/
and the repository is at github: https://github.com/martin8883/MikroTik-API


Feel free to ask if you have any questions or issues.

Regards
Martin

connection timeout doesn’t work..

add to API.pm

sub connect {

SSL_cipher_list => ‘HIGH’,

  • Timeout => $self->get_timeout()

    }

=head1 ACCESSORS

  • =head2 $api->get_timeout(), $api->set_timeout( $timeout )

  • =cut

  • has ‘timeout’ => ( is => ‘ro’, reader => ‘get_timeout’, writer => ‘set_timeout’, isa => ‘Int’ );

Hi kheeva,
thank you and sorry. I already implemented the timeout and some type of connection probing (useful for long lasting connections).
I will push it to github and CPAN later this day.
Regards
Martin

Hi, Martin.

Thanks a lot for your job :slight_smile:

Is it possible to run cmd through API like that:

/ip/firewall/filter/remove [/ip firewall filter find]

?

Version 1.0.2 is available at github and uploaded to cpan. I guess it will be listed in the next hours.

No, not as far as I know. Not because of limitations in the Perl implementation but the way how the API works. I´m not an expert for this API, but if I look here at how the API works, I cannot imagine a way to do this:
http://wiki.mikrotik.com/wiki/Manual:API

I would do it this way (of course, this could cause many many calls but I don´t think, they hurt):

my ( $ret, @rules ) = $api->query( '/ip/firewall/filter/find', {}, {} );
foreach my $ule ( @rules ) {
	$api->cmd( '/ip/firewall/filter/remove', {
		'.id' => $rule->{'.id'},
	});
}

But you can also have a look to other API implementations (C/PHP/Python/…) - if you find a possibility there, it will also be possible with the Perl API. Or I can implement it as soon as I know how the API calls have to be.

Edit: It is definitly not possible because find is no API command, see: http://wiki.mikrotik.com/wiki/API_command_notes#Scripting_commands

If you often have to to run the same command, you could either place a static script at the router or dynamically build the script, upload it and then run it by API /system/script/run

That notes section is a little outdated… I updated it to reflect the real situation with “find”, or least, as it was last I checked. And the situation is that “find” is supported, but without support for queries. Results are in the “ret” property of the !done reply.

Ah, thank you for information.
So do you think something like kheeva wants to do (remove all Firewall rules: /ip/firewall/filter/remove [/ip firewall filter find] ) is possible by API?

As find is so useless by API, I would not put much effort in this if there are changes in the implementation required.

Yes, but with two API calls.

One for “/ip/firewall/filter/find”, and another one with “/ip/firewall/filter/remove” that has “numbers” set to the value of “ret”.

Oh, and BTW, some RouterOS versions use “;” as a separator, while others use “,”… You should replace any “;” to “,” prior to using the “ret” value.

I was looking at the reference page, and I have a question…

$api->query(_$command,_\%attributes,_\%conditions_)

How are the %conditions chained? AND? OR? Do you allow for custom operator query words (You know, the “?#…” kind) or otherwise allow different logical operations as part of the conditions?

The query is based on this commit: https://github.com/elcamlost/mikrotik-perl-api/commit/10e5da1fd0ccb4a249ed3047c1d22c97251f666e
So it is no complete implementation of all possibilites of query. It is a very simple AND.

For example
die Dumper( $api->query(‘/interface/print’, {}, { type => ‘ether’, slave => ‘true’, ‘fast-path’ => ‘true’, running => ‘true’ } ) );
results in
?type=ether
?slave=true
?fast-path=true
?running=true

No possibility at the moment to work with ?#.
Perhaps I will rework this if I need it at some time. But then the whole data structure of query must be reworked, because at the moment it is a hash, that is not ordered. A good syntax would be similar to DBIx::Class::ResultSet: http://search.cpan.org/dist/DBIx-Class/lib/DBIx/Class/ResultSet.pm#search
This has a simple syntax like before, but also possible to use logical operators
{ -or => { type => ‘ether’, type => ‘vlan’, fast-path => ‘true’ }, slave => ‘true’ }

Everything else is possible except ?#, so no chance to query something other than AND.
{ ‘>tx-errors’ => 0, ‘<tx-errors’ => 17 }

It is a very simple AND.

For example
die Dumper( $api->query(‘/interface/print’, {}, { type => ‘ether’, slave => ‘true’, ‘fast-path’ => ‘true’, running => ‘true’ } ) );
results in
?type=ether
?slave=true
?fast-path=true
?running=true

Last I checked, having no operators is supposed to OR the criteria. Then again, I’ve never used “operator”-less queries (not with multiple criteria that is), so I could be wrong on that one.

Anyway…

IMHO, a class with a fluent interface that chains one operand against the result of everything before it is better, in that it allows for more cases to be addressed
(See my PHP client’s Query class for a PHP analog)

And a string parser (that parses a line like the one you’d have in CLI) would be best (but that one’s haaard, especially if you want to parse braces too).

I checked it and without operators, the conditions were seen as AND.

Nevertheless, at the moment I have no need to implement advanced operators. I will if I need them or if I have really boredom. But this won´t be in the next weeks. If someone else wants to implement - feel free to do so, I will accept pull requests.

marting
Please consider applying the patch from my bug report:
https://rt.cpan.org/Public/Bug/Display.html?id=111476

Hi lavv,
I already merged it, thank you!
Regards
Martin

@marting

Hi Martin,

Please consider merging a fix for post-v6.43 login method.

Thanks!
Artem

Sorry, I missed the fact that the old method has been removed with 6.45.
The changes (previously only on GitHub) are now also available with CPAN: https://metacpan.org/pod/MikroTik::API (v1.1.0). It precedencs new method and falls back to the old one.
Please test it carefully before production use, there were many PullRequests (thank you very much for those!!!) included in this release. Also some changed error handling (not dying so fast but use of errorcodes).

Also not very happy with plaintext auth method introduced with 6.43 (why???). So I postponed the release quite long.

New release 2.0.0 with change from Moose to Moo. Should have a little less compile time:
https://metacpan.org/release/MikroTik-API
https://github.com/martin8883/MikroTik-API/releases/tag/v2.0.0

  Adding route: 100.100.0.0/24 
>>> /ip/route/add
>>> =type=blackhole
>>> =bgp-origin=igp
>>> =bgp-communities=65000:5002
>>> =dst-address=100.100.0.0/24 
start read_len
read_len got 5
recv 5
<<< !trap
start read_len
read_len got 64
recv 64
<<< =message=value of dst-address must have number address after '/'
start read_len
read_len got 0
start read_len
read_len got 5
recv 5

This should be working?? Or, am I being stupid?