Ubic

 view release on metacpan or  search on metacpan

lib/Ubic/Cmd.pm  view on Meta::CPAN

    unless ($count) {
        # But if none of X subservices support our custom command, something is obviously wrong.
        if ($service->isa('Ubic::Multiservice')) {
            die "None of ".$service->full_name." subservices support $command";
        }
        else {
            # it is unlikely that this error will happen, because we already checked that $service supports $command
            die "$command unsupported";
        }
    }

    # TODO - what if X want to implement custom command itself?
    # should custom commands have different types, "try to call me in each subservice" and "call me for multiservice itself"?

    return;
}

sub usage {
    my $self = _obj(shift);
    my $command = shift;
    print STDERR "Unknown command '$command'. See 'ubic help'.\n";
    exit(2); # or exit(3)? see LSB for details
}


sub traverse($$$) {
    my $self = _obj(shift);
    my ($service, $callback, $indent) = @_;
    $indent ||= 0;

    if (not defined $service) {
        $service = Ubic->root_service;
    }
    elsif (not blessed($service)) {
        $service = Ubic->service($service);
    }
    my $name = $service->full_name;

    if ($service->isa('Ubic::Multiservice')) {
        if ($service->full_name) {
            print ' ' x $indent, $service->full_name, "\n";
            $indent = $indent + 4;
        }
        for my $subservice ($service->services) {
            $self->traverse($subservice, $callback, $indent); # FIXME - remember result
        }
    }
    else {
        print(' ' x $indent);
        return $callback->($service, $indent);
    }
}

sub print_status($$;$$) {
    my $self = _obj(shift);
    my $service = shift;
    my $force_cached = shift;
    my $results = shift || Ubic::Cmd::Results->new;

    # TODO - use Credentials instead
    my $user = getpwuid($>);
    unless (defined $user) {
        die "Can't detect user by uid $>";
    }

    my $max_offset = 0;
    $self->traverse($service, sub {
        my ($service, $indent) = @_;
        my $name = $service->full_name;
        print $name;

        # calculating the number of tabs to separate service name from status
        # status will be aligned whenever possible without sacrificing the real-time properties
        # i.e., we add several tabs to align status with previous lines, but following lines can increase the number of tabs if necessary
        # TODO - there are two possibilities to improve this:
        # 1) look at the further *simple* services and add tabs:
        # blah
        #     blah.a            off
        #     blah.blahblahblah off
        #     blah.c            off
        # (current implementation wouldn't align "blah.a" line correctly)
        # this would require the change to traverse() method api, though
        # 2) pre-compile whole service tree before printing anything
        # but output speed would suffer
        my $offset = length($name) + $indent;
        if ($offset < $max_offset) {
            print "\t" x (int($max_offset) / 8 - int($offset / 8));
        }
        else {
            $max_offset = $offset;
        }
        print "\t";

        my $enabled = Ubic->is_enabled($name);
        unless ($enabled) {
            print "off\n";
            $results->add(result('down'));
            return;
        }

        my $status;
        my $cached;
        if ($force_cached or ($> and $user ne Ubic->service($name)->user)) {
            $status = Ubic->cached_status($name);
            $cached = 1;
        }
        else {
            $status = eval { Ubic->status($name) };
            if ($@) {
                $status = result($@);
            }
        }
        if ($status->status eq 'running') {
            $results->print($status);
        }
        else {
            $results->print($status, 'bad'); # up and not running is always bad
        }
    });

    # TODO - print actual uplevel service's status, it can be service-specific



( run in 1.384 second using v1.01-cache-2.11-cpan-39bf76dae61 )