1

I have several Nagios plugins that were using Nagios::Plugin. The module is now deprecated and was substituted by Monitoring::Plugin.

As several distributions are not updated yet I check in the code which module is available

sub load_module {

    my @names = @_;
    my $loaded_module;

    for my $name (@names) {

        my $file = $name;

        # requires need either a bare word or a file name
        $file =~ s{::}{/}gsxm;
        $file .= '.pm';

        eval {
            require $file;
            $name->import();
        };
        if ( !$EVAL_ERROR ) {
            $loaded_module = $name;
            last;
        }
    }

    if ( !$loaded_module ) {
        # handle error ...
        exit 2;
    }

    return $loaded_module;

}

my $plugin_module = load_module( 'Monitoring::Plugin', 'Nagios::Plugin' );
my $plugin_threshold_module = load_module( 'Monitoring::Plugin::Threshold', 'Nagios::Plugin::Threshold' );

I used to check for the module availability in a Makefile.PL file with

requires 'Nagios::Plugin'            => 0;
requires 'Nagios::Plugin::Threshold' => 0;

and the use the module in my plugin.

Is there a standard way in Makefile.PL to check for a module (i.e., Monitoring::Plugins) and if not available check if another option is available (i.e., Nagios::Plugin::)?

Matteo
  • 14,696
  • 9
  • 68
  • 106
  • What do you mean by "only on distributions where the new module is already present."? Are yo relying on your OS vendor to provide your Perl modules for you? – Len Jaffe Mar 09 '15 at 15:34
  • Not me but a lot of people do. – Matteo Mar 09 '15 at 15:36
  • Why not just make `Monitoring::Plugin` a prerequisite and force users to install it if it's not available? At some point, `Monitoring::Plugin` and `Nagios::Plugin` will probably diverge, and your code will break for users who have `Nagios::Plugin`, without being warned by your install process. – ThisSuitIsBlackNot Mar 09 '15 at 18:51
  • They will not diverge, Nagios::Plugin is not developed anymore and they "renamed" it. The plugin is also packaged as RPM for RedHat, forcing people to install the new one will force me to package it (and maintain the RPM package). – Matteo Mar 09 '15 at 18:58
  • @Matteo They will diverge if the Monitoring Plugins people decide to change the API. I'm not saying they will, at least not any time soon, but it could happen. I don't understand what you mean by "forcing people to install the new one will force me to package it." [I read](https://bugzilla.redhat.com/show_bug.cgi?id=1054340#c71) that RedHat was going to make `yum update` of `nagios-plugins` install `monitoring-plugins`; I assume the same would apply to the package providing `Monitoring::Plugin` (if there is a separate package). Why would you have to package it yourself? – ThisSuitIsBlackNot Mar 09 '15 at 19:29
  • RedHat will do it but not for current versions. But anyway it could be interesting to know how to switch from two different modules providing a similar functionality – Matteo Mar 09 '15 at 19:41
  • @Matteo I'm not sure if that's doable with `Makefile.PL`, but you can certainly do it in your Perl code. Is that an option for you? – ThisSuitIsBlackNot Mar 09 '15 at 19:56
  • Yes, doing it the code is surely an option, I was just wandering what was the "best" way to do it – Matteo Mar 09 '15 at 19:58
  • See [How can I check if I have a Perl module before using it?](http://stackoverflow.com/q/251694/176646) and [How can I conditionally import a package in Perl?](http://stackoverflow.com/q/3957498/176646). – ThisSuitIsBlackNot Mar 09 '15 at 20:04

1 Answers1

1

The Makefile.PL is just a program, you can do the same check you're doing at runtime.

my %prereqs = (
    ...declare your static prereqs...
);

if( eval { require Monitoring::Plugin } ) {
    $prereqs{'Monitoring::Plugin'};
}
else {
    $prereqs{'Nagios::Plugin'};
}

WriteMakefile(
    ...blah blah blah...

    PREREQ_PM => \%prereqs
);

Other module build systems such as Module::Install and Dist::Zilla may support plugins to do that for you, but the basic result will be the same.

Note that this will generate a META file for your distribution describing your prerequisites. It will not have this logic and instead will show your module requiring whatever the outcome was at the time you built your distribution, there is no means in the spec to express what you want. This will not break anything, CPAN module installers will run the Makefile.PL and trust what it says over the META file so long as dynamic_config is true (which it is by default). However, the dynamic nature of your requirements will not be shown on things like https://metacpan.org.

Schwern
  • 153,029
  • 25
  • 195
  • 336