Changeset 1264

Show
Ignore:
Timestamp:
11/29/06 17:53:53 (5 years ago)
Author:
ilmari
Message:

r9169@vesla: ilmari | 2006-08-15 02:11:09 +0100
First shot at making Munin::Node::Runner object-oriented and
subclassable, in preparation of Munin::Node::Server.


user/group and environment setting don't work yet, though.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • people/ilmari/modularisation-branch/node/lib/Munin/Node/Runner.pm.in

    r1263 r1264  
    2222=head1 SYNOPSIS 
    2323 
    24 use Munin::Node::Runner qw(:all)
    25  
    26 load_services() or die "No services"; 
    27  
    28 for my $service (list_services()) { 
     24use Munin::Node::Runner
     25 
     26my $runner = Munin::Node::Runner->load_services() or die "No services"; 
     27 
     28for my $service ($runner->list_services()) { 
    2929 
    3030    # Print the service config 
    31     print run_service($service, 'config'); 
     31    print $runner->run_service($service, 'config'); 
    3232 
    3333    # Print the service values 
    34     print run_service($service); 
     34    print $runner->run_service($service); 
    3535} 
    3636 
     
    4545use strict; 
    4646use warnings; 
    47 use base qw(Exporter); 
    4847use POSIX qw(setsid); 
    4948use IPC::Run qw(run timeout new_chunker); 
    5049 
    51 use vars qw($VERSION $DEBUG $conffile $do_version $servicedir $sconfdir 
    52             $sconffile $paranoia $do_usage %EXPORT_TAGS @EXPORT_OK); 
    53  
     50use vars qw($VERSION); 
     51 
     52$VERSION = "@@VERSION@@"; 
    5453# Default values 
    55 $VERSION="@@VERSION@@"; 
    56 $DEBUG = 0; 
    57 $servicedir="@@CONFDIR@@/plugins"; 
    58 $sconfdir="@@CONFDIR@@/plugin-conf.d"; 
    59 $conffile="@@CONFDIR@@/munin-node.conf"; 
    60 $sconffile=undef; 
    61 $do_usage = 0; 
    62 $do_version = 0; 
    63 $paranoia = 0; 
    64  
    65 @EXPORT_OK = qw(load_services list_services run_service $VERSION $DEBUG 
    66                 $conffile $do_version $servicedir $sconfdir $sconffile 
    67                 $paranoia $do_usage); 
    68 %EXPORT_TAGS = ( all => \@EXPORT_OK ); 
    69  
    70 my %services; 
    71 my %nodes; 
    72  
    73 my $FQDN     =""; 
    74 my $defuser  = getpwnam ("@@PLUGINUSER@@"); 
    75 my $defgroup = getgrnam ("@@GROUP@@"); 
    76 my @ignores  = (); 
    77 my %sconf    = ('timeout' => 10); 
    78 my $caddr    = ""; 
    79 my $tls; 
    80 my %tls_verified = ( "level" => 0, "cert" => "", "verified" => 0, "required_depth" => 5 ); 
     54my %defaults = (servicedir   => "@@CONFDIR@@/plugins", 
     55                sconfdir     => "@@CONFDIR@@/plugin-conf.d", 
     56                conffile     => "@@CONFDIR@@/munin-node.conf", 
     57                defuser      => scalar getpwnam("@@PLUGINUSER@@"), 
     58                defgroup     => scalar getgrnam("@@GROUP@@"), 
     59                timeout      => 10, 
     60                tls_verified => { level          => 0, 
     61                                  cert           => '', 
     62                                  verified       => 0, 
     63                                  required_depth => 5, 
     64                                }, 
     65               ); 
    8166 
    8267sub list_services { 
    83     my $node = shift || $FQDN; 
    84     return grep { has_access ($_); } keys %{$nodes{$node}} if exists $nodes{$node}; 
     68    my $self = shift; 
     69    my $node = shift || $self->{config}{FQDN}; 
     70    my $nodes = $self->{nodes}; 
     71 
     72    return grep { $self->has_access($_); } keys %{$nodes->{$node}} if exists $nodes->{$node}; 
    8573} 
    8674 
    8775sub read_config { 
    88     if (!check_perms ($servicedir) or !check_perms ($conffile)) { 
     76    my $self = shift; 
     77    my $conf = $self->{config}; 
     78    my $conffile = $conf->{conffile}; 
     79    my $servicedir = $conf->{servicedir}; 
     80 
     81    if (!$self->check_perms($servicedir) or !$self->check_perms($conffile)) { 
    8982        die "Fatal error. Bailing out."; 
    9083    } 
    9184 
    92     if (! -f $conffile) { 
    93         print "ERROR: Cannot open $conffile\n"; 
    94         exit 1; 
    95     } 
    96  
    97     open FILE, $conffile or die "Cannot open $conffile\n"; 
    98     while (<FILE>) { 
     85    open(my $file, $conffile) or die "Cannot open $conffile: $!\n"; 
     86    while (<$file>) { 
    9987        chomp; 
    10088        s/#.*//;                # no comments 
     
    10492        /(^\w*)\s+(.*)/; 
    10593        if (($1 eq "host_name" or $1 eq "hostname") and $2) { 
    106             $FQDN=$2; 
     94            $conf->{FQDN} = $2; 
    10795        } elsif (($1 eq "default_plugin_user" or $1 eq "default_client_user") and $2) { 
    10896            my $tmpid = $2; 
    109             my $defuser = get_uid ($tmpid); 
    110             if (! defined ($defuser)) { 
     97            $conf->{defuser} = get_uid ($tmpid); 
     98            if (! defined ($conf->{defuser})) { 
    11199                die "Default user defined in \"$conffile\" does not exist ($tmpid)"; 
    112100            } 
    113101        } elsif (($1 eq "default_plugin_group" or $1 eq "default_client_group") and $2) { 
    114102            my $tmpid = $2; 
    115             $defgroup = get_gid ($tmpid); 
    116             if (! defined ($defgroup)) { 
     103            $conf->{defgroup} = get_gid ($tmpid); 
     104            if (! defined ($conf->{defgroup})) { 
    117105                die "Default group defined in \"$conffile\" does not exist ($tmpid)"; 
    118106            } 
    119107        } elsif (($1 eq "paranoia") and defined $2) { 
    120108            if ("$2" eq "no" or "$2" eq "false" or "$2" eq "off" or "$2" eq "0") { 
    121                 $paranoia = 0; 
     109                $conf->{paranoia} = 0; 
    122110            } else { 
    123                 $paranoia = 1; 
     111                $conf->{paranoia} = 1; 
    124112            } 
    125113        } elsif (($1 eq "ignore_file") and defined $2) { 
    126             push @ignores, $2; 
    127         } 
    128     } 
    129     $FQDN ||= &get_fq_hostname; 
    130     $ENV{FQDN}=$FQDN; 
     114            push @{$conf->{ignores}}, $2; 
     115        } 
     116    } 
     117    $conf->{FQDN} ||= get_fq_hostname(); 
     118    $ENV{FQDN} = $conf->{FQDN}; 
     119 
     120    if ($conf->{sconffile}) 
     121    { 
     122        if (!$self->load_auth_file($conf->{sconffile})) 
     123        { 
     124            warn "Something wicked happened while reading \"$conf->{sconffile}\". Check the previous log lin 
     125es for spesifics."; 
     126        } 
     127    } 
     128    else 
     129    { 
     130        my $sconfdir = $conf->{sconfdir}; 
     131        if (opendir(my $dir, $sconfdir)) 
     132        { 
     133          FILES: 
     134            for my $file (grep { -f "$sconfdir/$_" } readdir ($dir)) 
     135            { 
     136                next if $file =~ m/^\./; # Hidden files 
     137                next if $file !~ m/^([-\w.]+)$/; # Skip if any weird chars 
     138                $file = $1; # Not tainted anymore. 
     139                foreach my $regex (@{$self->{ignores}}) 
     140                { 
     141                    next FILES if $file =~ /$regex/; 
     142                } 
     143                if (!$self->load_auth_file("$sconfdir/$file")) 
     144                { 
     145                    warn "Something wicked happened while reading \"$sconfdir/$file\". Check the previous log lines for spesifics."; 
     146                } 
     147            } 
     148            closedir($dir); 
     149        } 
     150    } 
    131151} 
    132152 
    133153sub load_services { 
    134     read_config(); 
    135  
    136     if (opendir (DIR,$sconfdir)) 
    137     { 
     154    my $self = shift; 
     155    # Take config as first argument unless already initialised 
     156    # by a sublcass constructor 
     157    $self = bless {config => shift || {}}, $self unless ref $self; 
     158 
     159    # Load default values 
     160    my $conf = $self->{config}; 
     161    for my $key (keys %defaults) { 
     162        $conf->{$key} = $defaults{$key} unless exists $conf->{key}; 
     163    } 
     164 
     165    $self->read_config(); 
     166 
     167    my $services = $self->{services} ||= {}; 
     168    my $nodes = $self->{nodes} ||= {}; 
     169 
     170    my $servicedir = $conf->{servicedir}; 
     171    opendir(my $dir, $servicedir) or die "Cannot open plugindir: $servicedir $!"; 
    138172FILES: 
    139         for my $file (grep { -f "$sconfdir/$_" } readdir (DIR)) 
    140         { 
    141             next if $file =~ m/^\./; # Hidden files 
    142             next if $file !~ m/^([-\w.]+)$/; # Skip if any weird chars 
    143             $file = $1; # Not tainted anymore. 
    144             foreach my $regex (@ignores) 
    145             { 
    146                 next FILES if $file =~ /$regex/; 
    147             } 
    148             if (!load_auth_file ($sconfdir, $file, \%sconf)) 
    149             { 
    150                 warn "Something wicked happened while reading \"$servicedir/$file\". Check the previous log lines for spesifics."; 
    151             } 
    152         } 
    153         closedir (DIR); 
    154     } 
    155  
    156     opendir (DIR,$servicedir) || die "Cannot open plugindir: $servicedir $!"; 
    157 FILES: 
    158     for my $file (grep { -f "$servicedir/$_" } readdir(DIR)) { 
     173    for my $file (grep { -f "$servicedir/$_" } readdir($dir)) { 
    159174        next if $file =~ m/^\./; # Hidden files 
    160175        next if $file =~ m/.conf$/; # Config files 
    161176        next if $file !~ m/^([-\w.]+)$/; # Skip if any weird chars 
    162177        $file = $1; # Not tainted anymore. 
    163         foreach my $regex (@ignores
     178        foreach my $regex (@{$conf->{ignores}}
    164179        { 
    165180            next FILES if $file =~ /$regex/; 
    166181        } 
    167182        next if (! -x "$servicedir/$file"); # File not executeable 
    168         debug ("file: '$file'\n"); 
    169         $services{$file}=1; 
    170         my @rows = run_service($file,"config"); 
    171         my $node = get_var (\%sconf, $file, 'host_name'); 
     183 
     184        $self->debug("file: '$file'\n"); 
     185        $services->{$file}=1; 
     186        my @rows = $self->run_service($file, 'config'); 
     187        my $node = $self->get_var($file, 'host_name'); 
    172188 
    173189        for my $row (@rows) { 
    174           debug ("row: $row\n"); 
     190          $self->debug("row: $row\n"); 
    175191          if ($row =~ m/^host_name (.+)$/) { 
    176             debug ("Found host_name, using it\n"); 
     192            $self->debug("Found host_name, using it\n"); 
    177193            $node = $1; 
    178194          } 
    179195        } 
    180         $node ||= $FQDN; 
    181         $nodes{$node}{$file}=1; 
    182     } 
    183     closedir DIR; 
    184     return keys %services; 
     196        $node ||= $conf->{FQDN}; 
     197        $nodes->{$node}{$file}=1; 
     198    } 
     199    closedir($dir); 
     200    
     201    return $self; 
    185202} 
    186203 
    187204sub run_service { 
    188     my ($service,$command) = @_; 
     205    my ($self, $service, $command) = @_; 
     206    my $conf = $self->{config}; 
     207    my $servicedir = $conf->{servicedir}; 
     208 
    189209    $command ||= ''; 
    190210    my @lines = ();; 
    191211    my $timed_out = 0; 
    192     return "# Unknown service $service\n" 
    193       unless $services{$service} and ($caddr eq "" or has_access ($service)); 
     212    return "# Unknown service '$service'\n" 
     213      unless $self->{services}{$service} and $self->has_access($service); 
    194214 
    195215    # Untaint $service, we know it's safe (it's in the %services hash) 
     
    197217    $service = $1; 
    198218 
    199     my $timeout = get_var (\%sconf, $service, 'timeout'); 
    200     $timeout = $sconf{'timeout'} 
     219    if (!$self->check_perms("$servicedir/$service")) { 
     220        $self->logger("Error: unsafe permissions. Bailing out."); 
     221        return "# Unsafe permissions on service '$service'\n"; 
     222    } 
     223 
     224    my $timeout = $self->get_var($service, 'timeout'); 
     225    $timeout = $conf->{timeout} 
    201226      unless defined $timeout and $timeout =~ /^\d+$/; 
    202227 
     
    205230        $command = $1; 
    206231    } else { 
    207         logger("Unknown command '$command'"); 
     232        $self->logger("Unknown command '$command'"); 
    208233        return "# Unknown command '$command'\n"; 
    209234    } 
    210235 
    211236    my @run; 
    212     if (defined $sconf{$service}{'command'}) { 
     237    if (my $cmd = $self->get_var($service, 'command')) { 
    213238        @run = map { $_ eq '%c' ? "$servicedir/$service" : $_ } 
    214           @{$sconf{$service}{'command'}} 
     239          @$cmd; 
    215240    } else { 
    216241        @run = ("$servicedir/$service", $command); 
    217242    } 
     243 
     244    $self->debug("About to run '", join("', '", @run), "'\n"); 
    218245 
    219246    eval { 
    220247        run(\@run, 
    221248            '>', new_chunker("\n"), sub { push @lines, @_ }, 
    222             '2>', new_chunker("\n"), sub { logger("$service: $_[0]") }, 
    223             init => sub { setup_environment($service) }, 
     249            '2>', new_chunker("\n"), sub { $self->logger("$service: $_[0]") }, 
     250            init => sub { $self->setup_environment($service) }, 
    224251            timeout($timeout, exception => "plugin timed out"), 
    225252           ); 
     
    227254     
    228255    if (@!) { 
    229         logger("Error running $service: @!"); 
     256        $self->logger("Error running $service: @!"); 
    230257        return "# Error running $service: @!\n"; 
    231258    } 
     259    $self->logger("No output from service '$service'\n") unless @lines; 
    232260    return @lines; 
    233261} 
     
    235263# Called from the plugin child before exec. 
    236264sub setup_environment { 
    237     my $service = shift or die "internal error: service required"; 
     265    my ($self, $service) = @_; 
     266    die "internal error: service required" 
     267      unless $self and $service; 
     268 
     269    my $conf    = $self->{config}; 
     270    my $user    = $self->get_var($service, 'user'); 
     271    my $group   = $self->get_var($service, 'group'); 
     272    my $env;      $self->get_var($service, 'env', $env); 
     273             
    238274    POSIX::setsid(); 
    239     # Setting environment 
    240     $sconf{$service}{user}    = get_var (\%sconf, $service, 'user'); 
    241     $sconf{$service}{group}   = get_var (\%sconf, $service, 'group'); 
    242     $sconf{$service}{command} = get_var (\%sconf, $service, 'command'); 
    243     get_var (\%sconf, $service, 'env', \%{$sconf{$service}{env}}); 
    244              
    245275    if ($< == 0)                # If root... 
    246276    { 
    247277        # Giving up gid egid uid euid 
    248         my $u  = (defined $sconf{$service}{'user'}? 
    249                   $sconf{$service}{'user'}: 
    250                   $defuser); 
    251         my $g  = $defgroup; 
    252         my $gs = "$g $g" . 
    253           (defined $sconf{$service}{'group'} ? 
    254            " $sconf{$service}{group}" : ""); 
     278        my $u  = defined $user ? $user : $conf->{defuser}; 
     279        my $g  = $conf->{defgroup}; 
     280        my $gs = "$g $g" . (defined $group ? " $group" : ""); 
    255281                   
    256         debug ("Want to run as euid/egid $u/$g\n"); 
     282        $self->debug("Want to run as euid/egid $u/$g\n"); 
    257283 
    258284        $( = $g    unless $g == 0; 
     
    262288 
    263289        if ($> != $u or $g != (split (' ', $)))[0]) { 
    264             #                   net_write ("# Can't drop privileges. Bailing out. (wanted uid=", 
    265             #                       ($sconf{$service}{'user'} || $defuser), " gid=\"", 
    266             #                       $gs, "\"($g), got uid=$> gid=\"$)\"(", 
    267             #                       (split (' ', $)))[0], ").\n"); 
    268             logger ("Plugin \"$service\" Can't drop privileges. ". 
    269                     "Bailing out. (wanted uid=". 
    270                     ($sconf{$service}{'user'} || $defuser). " gid=\"". 
     290            $self->logger("Plugin \"$service\" Can't drop privileges. ". 
     291                    "Bailing out. (wanted uid=$u gid=\"". 
    271292                    $gs. "\"($g), got uid=$> gid=\"$)\"(". 
    272293                    (split (' ', $)))[0]. ")."); 
     
    274295        } 
    275296    } 
    276     debug ("Running as uid/gid/euid/egid $</$(/$>/$)\n"); 
    277     if (!check_perms ("$servicedir/$service")) { 
    278         net_write ("# Error: unsafe permissions. Bailing out."); 
    279         logger ("Error: unsafe permissions. Bailing out."); 
    280         exit 2; 
    281     } 
    282  
     297    $self->debug("Running as uid/gid/euid/egid $</$(/$>/$)\n"); 
    283298    # Setting environment... 
    284     if (defined $sconf{$service}{'env'}) { 
    285         foreach my $key (keys %{$sconf{$service}{'env'}}) { 
    286             debug ("Setting environment $key=$sconf{$service}{env}{$key}\n"); 
    287             $ENV{"$key"} = $sconf{$service}{'env'}{$key}; 
    288         } 
    289     } 
    290 
    291  
     299    foreach my $key (keys %$env) { 
     300        $self->debug("Setting environment $key=$env->{$key}\n"); 
     301        $ENV{"$key"} = $env->{$key}; 
     302    } 
     303
     304 
     305# Override for real access control 
    292306sub has_access { 
    293         my $serv   = shift; 
    294         my $host   = $caddr; 
    295         my $rights = get_var_arr (\%sconf, $serv, 'allow_deny'); 
    296  
    297         unless (@{$rights}) 
    298         { 
    299                 return 1; 
    300         } 
    301         debug ("Checking access: $host;$serv;\n"); 
    302         foreach my $ruleset (@{$rights}) 
    303         { 
    304                 foreach my $rule (@{$ruleset}) 
    305                 { 
    306                         debug ("Checking access: $host;$serv;". $rule->[0].";".$rule->[1]); 
    307                         if ($rule->[1] eq "tls" and $tls_verified{"verified"}) 
    308                         { # tls 
    309                                 if ($rule->[0] eq "allow") 
    310                                 { 
    311                                         return 1; 
    312                                 } 
    313                                 else 
    314                                 { 
    315                                         return 0; 
    316                                 } 
    317                         } 
    318 #                       elsif ($rule->[1] =~ /\//) 
    319 #                       { # CIDR 
    320 #                               print "DEBUG: CIDR $host;$serv;$rule->[1];\n"; 
    321 #                               return 1; 
    322 #                       } 
    323                         else 
    324                         { # regex 
    325                                 if ($host =~ m($rule->[1])) 
    326                                 { 
    327                                         if ($rule->[0] eq "allow") 
    328                                         { 
    329                                                 return 1; 
    330                                         } 
    331                                         else 
    332                                         { 
    333                                                 return 0; 
    334                                         } 
    335                                 } 
    336                         } 
    337                 } 
    338         } 
    339         return 1; 
     307    return 1; 
    340308} 
    341309 
    342310sub check_perms 
    343311{ 
    344     my $target = shift; 
    345     my @stat; 
     312    my ($self, $target) = @_; 
     313    my $conf = $self->{config}; 
     314 
    346315    return undef if (!defined $target); 
    347         return 1 if (!$paranoia); 
    348  
    349     if (! -e "$target") 
    350     { 
    351         warn "Failed to check permissions on nonexistant target: \"$target\""; 
     316    return 1 if (!$self->{paranoia}); 
     317 
     318    my @stat = stat ($target); 
     319    if (!@stat) 
     320    { 
     321        warn "Failed to check permissions on target: \"$target\": $!\n"; 
    352322        return undef; 
    353323    } 
    354324 
    355     @stat = stat ($target); 
    356325    if (!$stat[4] == 0 or 
    357326        ($stat[5] != 0 and $stat[2] & 00020) or 
     
    365334    { 
    366335        (my $dirname = $target) =~ s/[^\/]+$//; 
    367         return check_perms ($dirname); 
     336        return $self->check_perms($dirname); 
    368337    } 
    369338 
     
    397366sub load_auth_file 
    398367{ 
    399     my ($dir, $file, $sconf) = @_; 
     368    my ($self, $file) = @_; 
    400369    my $service = $file; 
    401  
    402     if (!defined $dir or !defined $file or !defined $sconf) 
    403     { 
    404         return undef; 
    405     } 
    406  
    407     return undef if (!check_perms ($dir)); 
    408     return undef if (!check_perms ("$dir/$file")); 
    409  
    410     if (!open (IN, "$dir/$file")) 
    411     { 
    412         warn "Could not open file \"$dir/$file\" for reading ($!), skipping plugin\n"; 
    413         return undef; 
    414     } 
    415     while (<IN>) 
     370    my $sconf = $self->{config}{services}; 
     371 
     372    return if (!$self->check_perms($file)); 
     373 
     374    my $in; 
     375    if (!open ($in, '<', $file)) 
     376    { 
     377        warn "Could not open file \"$file\" for reading ($!), skipping plugin\n"; 
     378        return; 
     379    } 
     380 
     381    while (<$in>) 
    416382    { 
    417383        chomp; 
     
    419385        next unless /\S/; 
    420386        s/\s+$//g; 
    421         debug ("Config: $service: $_\n"); 
     387        $self->debug("Config: $service: $_\n"); 
    422388        if (/^\s*\[([^\]]+)\]\s*$/) 
    423389        { 
     
    428394            my $tmpid = $1; 
    429395            $sconf->{$service}{'user'} = get_uid ($tmpid); 
    430             debug ("Config: $service->uid = ", $sconf->{$service}{'user'}, "\n"); 
     396            $self->debug("Config: $service->uid = ", $sconf->{$service}{'user'}, "\n"); 
    431397            if (!defined $sconf->{$service}{'user'}) 
    432398            { 
    433                 warn "User \"$tmpid\" in configuration file \"$dir/$file\" nonexistant. Skipping plugin."; 
     399                warn "User \"$tmpid\" in configuration file \"$file\" nonexistant. Skipping plugin."; 
    434400                return undef; 
    435401            } 
     
    449415 
    450416                my $g = get_gid ($group); 
    451                 debug ("Config: $service->gid = $g\n") if defined $g; 
     417                $self->debug("Config: $service->gid = $g\n") if defined $g; 
    452418                if (!defined $g and !$optional) 
    453419                { 
    454                     warn "Group \"$group\" in configuration file \"$dir/$file\" nonexistant. Skipping plugin."; 
     420                    warn "Group \"$group\" in configuration file \"$file\" nonexistant. Skipping plugin."; 
    455421                    return undef; 
    456422                } 
    457423                elsif (!defined $g and $optional) 
    458424                { 
    459                     debug ("Skipping \"$group\" (optional).\n"); 
     425                    $self->debug("Skipping \"$group\" (optional).\n"); 
    460426                    next; 
    461427                } 
     
    481447        { 
    482448            $sconf->{$service}{'timeout'} = $1; 
    483             debug ("$service: setting timeout to $1\n"); 
     449            $self->debug("$service: setting timeout to $1\n"); 
    484450        } 
    485451        elsif (/^\s*(allow)\s+(.+)\s*$/ or /^\s*(deny)\s+(.+)\s*$/) 
    486452        { 
    487453            push (@{$sconf->{$service}{'allow_deny'}}, [$1, $2]); 
    488             debug ("Pushing allow_deny: $1, $2\n"); 
     454            $self->debug("Pushing allow_deny: $1, $2\n"); 
    489455        } 
    490456        elsif (/^\s*env\s+([^=\s]+)\s*=\s*(.+)$/) 
    491457        { 
    492458            $sconf->{$service}{'env'}{$1} = $2; 
    493             debug ("Saving $service->env->$1 = $2...\n"); 
    494             warn "Warning: Deprecated format in \"$dir/$file\" under \"[$service]\" (\"env $1=$2\" should be rewritten to \"env.$1 $2\")."; 
     459            $self->debug("Saving $service->env->$1 = $2...\n"); 
     460            warn "Warning: Deprecated format in \"$file\" under \"[$service]\" (\"env $1=$2\" should be rewritten to \"env.$1 $2\")."; 
    495461        } 
    496462        elsif (/^\s*env\.(\S+)\s+(.+)$/) 
    497463        { 
    498464            $sconf->{$service}{'env'}{$1} = $2; 
    499             debug ("Saving $service->env->$1 = $2...\n"); 
     465            $self->debug("Saving $service->env->$1 = $2...\n"); 
    500466        } 
    501467        elsif (/^\s*(\w+)\s+(.+)$/) 
    502468        { 
    503469            $sconf->{$service}{'env'}{"lrrd_$1"} = $2; 
    504             debug ("Saving $service->env->lrrd_$1 = $2...\n"); 
    505             warn "Warning: Deprecated format in \"$dir/$file\" under \"[$service]\" (\"$1 $2\" should be rewritten to \"env lrrd_$1=$2\")."; 
     470            $self->debug("Saving $service->env->lrrd_$1 = $2...\n"); 
     471            warn "Warning: Deprecated format in \"$file\" under \"[$service]\" (\"$1 $2\" should be rewritten to \"env lrrd_$1=$2\")."; 
    506472        } 
    507473        elsif (/\S/) 
    508474        { 
    509             warn "Warning: Unknown config option in \"$dir/$file\" under \"[$service]\": $_"; 
    510         } 
    511  
    512     } 
    513     close (IN); 
     475            warn "Warning: Unknown config option in \"$file\" under \"[$service]\": $_"; 
     476        } 
     477 
     478    } 
     479    close($in); 
    514480 
    515481    return 1; 
     
    518484sub get_var 
    519485{ 
    520     my $sconf   = shift; 
     486    my $self    = shift; 
    521487    my $name    = shift; 
    522488    my $var     = shift; 
    523489    my $env     = shift; 
     490    my $sconf   = $self->{config}{services}; 
    524491 
    525492    if ($var eq 'env' and !defined $env) 
     
    537504        (my $tmpservice = $wildservice) =~ s/\*$//; 
    538505        next unless ($name =~ /^$tmpservice/); 
    539         debug ("Checking $wildservice...\n"); 
     506        $self->debug("Checking $wildservice...\n"); 
    540507 
    541508        if ($var eq 'env') 
     
    548515                    { 
    549516                        $sconf->{$name}{'env'}{$key} = $sconf->{$wildservice}{'env'}{$key}; 
    550                         debug ("Saving $wildservice->$key\n"); 
     517                        $self->debug("Saving $wildservice->$key\n"); 
    551518                    } 
    552519                } 
     
    567534sub get_var_arr 
    568535{ 
    569     my $sconf   = shift; 
     536    my $self    = shift; 
    570537    my $name    = shift; 
    571538    my $var     = shift; 
     539    my $sconf   = $self->{config}{services}; 
    572540    my $result  = []; 
    573541 
     
    581549        (my $tmpservice = $wildservice) =~ s/\*$//; 
    582550        next unless ($name =~ /^$tmpservice/); 
    583         debug ("Checking $wildservice...\n"); 
     551        $self->debug("Checking $wildservice...\n"); 
    584552 
    585553        if (defined $sconf->{$wildservice}{$var}) 
    586554        { 
    587555            push (@{$result}, $sconf->{$wildservice}{$var}); 
    588             debug ("Pushing: |", join (';', @{$sconf->{$wildservice}{$var}}), "|\n"); 
     556            $self->debug("Pushing: |", join (';', @{$sconf->{$wildservice}{$var}}), "|\n"); 
    589557        } 
    590558    } 
     
    607575 
    608576sub debug { 
    609     print STDERR "DEBUG: ", @_ if $DEBUG; 
     577    my $self = shift; 
     578    print STDERR "DEBUG: ", @_ if $self->{config}{DEBUG}; 
    610579} 
    611580 
    612581sub net_write { 
     582    my $self = shift; 
    613583    print STDERR @_; 
    614584} 
    615585sub logger { 
     586    my $self = shift; 
    616587    print STDERR @_; 
    617588} 
  • people/ilmari/modularisation-branch/node/munin-run.in

    r1044 r1264  
    2323use strict; 
    2424use Getopt::Long; 
    25 use Munin::Node::Runner qw(:all)
     25use Munin::Node::Runner
    2626# "Clean" environment to disable taint-checking on the environment. We _know_ 
    2727# that the environment is insecure, but we want to let admins shoot themselves 
     
    4040delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; 
    4141 
    42 $do_usage=1  unless  
    43 GetOptions ( "config=s"     => \$conffile, 
    44              "debug!"       => \$DEBUG, 
    45              "version!"     => \$do_version, 
    46              "servicedir=s" => \$servicedir, 
    47              "sconfdir=s"   => \$sconfdir, 
    48              "sconffile=s"  => \$sconffile, 
    49              "paranoia!"    => \$paranoia, 
    50              "help"         => \$do_usage ); 
     42my $config = {}; 
     43GetOptions ($config, 
     44            qw(config=s 
     45               debug! 
     46               version! 
     47               servicedir=s 
     48               sconfdir=s 
     49               sconffile=s 
     50               paranoia! 
     51               help)) 
     52  or $config->{help} = 1; 
    5153 
    52 if ($do_usage
     54if ($config->{help}
    5355{ 
    5456    print "Usage: $0 [options] 
     
    7375} 
    7476 
    75 if ($conffile =~ /^([-\/\@_\w\.]+)$/)  
    76 
    77     $conffile = $1;                     # $data now untainted 
    78 }  
    79 else  
    80 
    81     die "Bad data in $conffile";        # log this somewhere 
     77for my $option (qw(conffile sconfdir sconffile servicedir)) { 
     78    next unless exists $config->{$option}; 
     79    if ($config->{$option} =~ /^([-\/\@_\w\.]+)$/) { 
     80        $config->{$option} = $1;                     # $data now untainted 
     81    } else { 
     82        die "Bad data in $option";        # log this somewhere 
     83    } 
    8284} 
    83 if ($sconfdir =~ /^([-\/\@_\w\.]+)$/)  
    84 
    85     $sconfdir = $1;                     # $data now untainted 
    86 }  
    87 else  
    88 
    89     die "Bad data in $sconfdir";        # log this somewhere 
    90 
    91 if (defined $sconffile and $sconffile =~ /^([-\/\@_\w\.]+)$/)  
    92 
    93     $sconffile = $1;                     # $data now untainted 
    94 }  
    95 elsif (defined $sconffile)  
    96 
    97     die "Bad data in $sconffile";        # log this somewhere 
    98 
    99 if ($servicedir =~ /^([-\/\@_\w\.]+)$/)  
    100 
    101     $servicedir = $1;                     # $data now untainted 
    102 }  
    103 else  
    104 
    105     die "Bad data in $servicedir";        # log this somewhere 
    106 
    107  
    108 if ($do_version) 
     85if ($config->{version}) 
    10986{ 
    11087        print <<"EOT"; 
    111 munin-run (munin-node) version $VERSION. 
     88munin-run (munin-node) version $Munin::Node::Runner::VERSION. 
    11289Written by Jimmy Olsen / Linpro AS 
    11390 
     
    123100} 
    124101 
    125 load_services(); 
    126 print run_service(@ARGV); 
     102my $runner = Munin::Node::Runner->load_services($config); 
     103print $runner->run_service(@ARGV); 
    127104 
    128105=head1 NAME 
  • people/ilmari/modularisation-branch/t/node-runner.t

    r1043 r1264  
    22# Tests for the Munin::Node::Runner module 
    33 
    4 use Test::More tests => 9
     4use Test::More tests => 10
    55use strict; 
    66 
    77sub run { 
    8     my $plugin = shift; 
    9     my @lines = run_service($plugin, @_) 
    10       or warn "No output from '$plugin' plugin\n"; 
     8    my $runner = shift; 
     9    my @lines = $runner->run_service(@_) 
     10      or warn "No output from '$_[0]' plugin\n"; 
    1111     
    1212    my %ret; 
     
    2222} 
    2323 
    24 BEGIN { use_ok('Munin::Node::Runner', qw(:all)); } 
     24BEGIN { use_ok('Munin::Node::Runner'); } 
    2525 
    26 ok(load_services(), "loading services"); 
    27 ok(list_services(), "listing services"); 
     26my $runner; 
     27ok    ($runner = Munin::Node::Runner->load_services, "loading services"); 
     28isa_ok($runner, 'Munin::Node::Runner'); 
     29ok    ($runner->list_services(), "listing services"); 
    2830 
    2931SKIP: { 
     
    3234      unless getpwnam('nobody') && getgrnam('nogroup'); 
    3335 
    34     my %id = run('id_default'); 
     36    my %id = run($runner, 'id_default'); 
    3537    is($id{uid}{extinfo}, 'nobody', "default user"); 
    3638    like($id{gid}{extinfo}, qr/\bnogroup\b/, "default group"); 
    3739     
    38     my %id = run('id_root'); 
     40    my %id = run($runner, 'id_root'); 
    3941    is($id{uid}{value}, 0, 'user override'); 
    4042    like($id{gid}{extinfo}, qr/\broot\b/, 'group override'); 
    4143} 
    4244 
    43 my %env = run('env'); 
     45my %env = run($runner, 'env'); 
    4446is_deeply(\%env, 
    4547          { 
     
    5355    local $TODO = "munin-run doesn't handle this"; 
    5456 
    55     my %config = run('env config'); 
     57    my %config = run($runner, qw(env config)); 
    5658    is($config{host_name}, 'test.example.com', 'host_name override'); 
    5759