The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

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 $cv  = AE::cv;
  my $tag = $api->command(
      '/system/resource/print',
      {'.proplist' => 'board-name,version,uptime'} => sub {
          my ($api, $err, $list) = @_;
          ...;
          $cv->send;
      }
  );
  $cv->recv;

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

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

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

          ...;
      }
  );
 
  # Promises
  $cv  = AE::cv;
  $api->cmd_p('/interface/print')
      ->then(sub { my $res = shift }, sub { my ($err, $attr) = @_ })
      ->finally($cv);
  $cv->recv;

DESCRIPTION

Both blocking and non-blocking (don't mix them though) interface to a MikroTik API service. With queries, command subscriptions and optional Promises. Starting from v0.5 this module is an AnyEvent user.

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.

new_login

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

Use new login scheme introduced in RouterOS v6.43 and fallback to previous one for older systems. Since in this mode a password will be send in clear text, for some time, it will be default only for "tls" connections.

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
  my $t = AE::timer 10, 0, 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 list with hashrefs containing elements returned by a host. You can append a callback for non-blocking calls.

In a case of error, returned value may keep additional attributes such as category or an error code. 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 promise instead of accepting a callback. Promises v0.99+ is required for this functionality.

subscribe

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

  AE::timer 3, 0, 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-2019.

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