NAME

MikroTik::Client - Non-blocking interface to MikroTik API

SYNOPSIS

my $api = MikroTik::Client->new();

# Blocking
my $list = $api->command(
    '/interface/print',
    {'.proplist' => '.id,name,type'},
    {type        => ['ipip-tunnel', 'gre-tunnel'], running => 'true'}
);
if (my $err = $api->error) { die "$err\n" }
printf "%s: %s\n", $_->{name}, $_->{type} for @$list;


# Non-blocking
my $tag = $api->command(
    '/system/resource/print',
    {'.proplist' => 'board-name,version,uptime'} => sub {
        my ($api, $err, $list) = @_;
        ...;
    }
);
Mojo::IOLoop->start();

# Subscribe
$tag = $api->subscribe(
    '/interface/listen' => sub {
        my ($api, $err, $el) = @_;
        ...;
    }
);
Mojo::IOLoop->timer(3 => sub { $api->cancel($tag) });
Mojo::IOLoop->start();

# Errors handling
$api->command(
    '/random/command' => sub {
        my ($api, $err, $list) = @_;

        if ($err) {
            warn "Error: $err, category: " . $list->[0]{category};
            return;
        }

        ...;
    }
);
Mojo::IOLoop->start();

# Promises
$api->cmd_p('/interface/print')
    ->then(sub { my $res = shift }, sub { my ($err, $attr) = @_ })
    ->finally(sub { Mojo::IOLoop->stop() });
Mojo::IOLoop->start();

DESCRIPTION

Both blocking and non-blocking interface to a MikroTik API service. With queries, command subscriptions and Promises/A+ (courtesy of an I/O loop). Based on Mojo::IOLoop and would work alongside EV.

ATTRIBUTES

MikroTik::Client implements the following attributes.

error

my $last_error = $api->error;

Keeps an error from last "command" call. Empty string on successful commands.

host

my $host = $api->host;
$api     = $api->host('border-gw.local');

Host name or IP address to connect to. Defaults to 192.168.88.1.

ioloop

my $loop = $api->ioloop;
$api     = $api->loop(Mojo::IOLoop->new());

Event loop object to use for blocking operations, defaults to Mojo::IOLoop object.

new_login

my $new_login = $api->new_login;
$api          = $api->new_login(1);

Use new login scheme introduced in RouterOS v6.43. Since it's requires clear text password, it will be default only for "tls" connections.

Cause v6.43 actually accepts both schemes, it's kinda lax change. Future behaviour will depend on MikroTik policies.

password

my $pass = $api->password;
$api     = $api->password('secret');

Password for authentication. Empty string by default.

port

my $port = $api->port;
$api     = $api->port(8000);

API service port for connection. Defaults to 8729 and 8728 for TLS and clear text connections respectively.

timeout

my $timeout = $api->timeout;
$api        = $api->timeout(15);

Timeout in seconds for sending request and receiving response before command will be canceled. Default is 10 seconds.

tls

my $tls = $api->tls;
$api    = $api->tls(1);

Use TLS for connection. Enabled by default.

user

my $user = $api->user;
$api     = $api->user('admin');

User name for authentication purposes. Defaults to admin.

METHODS

cancel

# subscribe to a command output
my $tag = $api->subscribe('/ping', {address => '127.0.0.1'} => sub {...});

# cancel command after 10 seconds
Mojo::IOLoop->timer(10 => sub { $api->cancel($tag) });

# or with callback
$api->cancel($tag => sub {...});

Cancels background commands. Can accept a callback as last argument.

cmd

my $list = $api->cmd('/interface/print');

An alias for "command".

cmd_p

my $promise = $api->cmd_p('/interface/print');

An alias for "command_p".

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) {...}
});

# Omit attributes
$api->command('/user/print', undef, {name => 'admin'} => sub {...});

# Errors handling
$list = $api->command('/random/command');
if (my $err = $api->error) {
    die "Error: $err, category: " . $list->[0]{category};
}

Executes a command on a remote host and returns Mojo::Collection with hashrefs containing elements returned by a host. You can append a callback for non-blocking calls.

In a case of error it may return extra attributes to !trap or !fatal API replies in addition to error messages in an "error" attribute or an $err argument. You should never rely on defines of the result to catch errors.

For a query syntax refer to MikroTik::Client::Query.

command_p

my $promise = $api->command_p('/interface/print');

$promise->then(
sub {
    my $res = shift;
    ...
})->catch(sub {
    my ($err, $attr) = @_;
});

Same as "command", but always performs requests non-blocking and returns a Mojo::Promise object instead of accepting a callback. Mojolicious v7.54+ is required for promises functionality.

subscribe

my $tag = $api->subscribe('/ping',
    {address => '127.0.0.1'} => sub {
      my ($api, $err, $res) = @_;
    });

Mojo::IOLoop->timer(
    3 => sub { $api->cancel($tag) }
);

Subscribe to an output of commands with continuous responses such as listen or ping. Should be terminated with "cancel".

DEBUGGING

You can set the MIKROTIK_CLIENT_DEBUG environment variable to get some debug output printed to stderr.

Also, you can change connection timeout with the MIKROTIK_CLIENT_CONNTIMEOUT variable.

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.

SEE ALSO

https://wiki.mikrotik.com/wiki/Manual:API, https://github.com/anparker/api-mikrotik