File Coverage

lib/ControlFreak/Console.pm
Criterion Covered Total %
statement 63 74 85.1
branch 5 10 50.0
condition 1 4 25.0
subroutine 13 15 86.6
pod 1 3 33.3
total 83 106 78.3


line stmt bran cond sub pod time code
1             package ControlFreak::Console;
2 8     8   46 use strict;
  8         16  
  8         315  
3 8     8   45 use warnings;
  8         15  
  8         280  
4              
5 8     8   45 use Carp;
  8         17  
  8         684  
6 8     8   8451 use AnyEvent::Socket();
  8         155816  
  8         373  
7 8     8   278 use AnyEvent::Handle();
  8         15  
  8         178  
8 8     8   48 use Scalar::Util();
  8         16  
  8         510  
9              
10             our $CRLF = "\015\12";
11              
12 8         131 use Object::Tiny qw{
13             host
14             service
15             full
16             started
17 8     8   44 };
  8         21  
18              
19             sub new {
20 1     1 0 27 my $console = shift->SUPER::new(@_);
21 1         17 my %param = @_;
22 1 50       14 $console->{ctrl} = $param{ctrl}
23             or croak "Console requires a controller";
24 1         8 Scalar::Util::weaken($console->{ctrl});
25 1         3 $console->{started} = 0;
26 1         7 $param{ctrl}->set_console($console);
27 1         3 $console->{full} = 1;
28 1         7 return $console;
29             }
30              
31             =head1 NAME
32              
33             ControlFreak::Console - Handles all communications with ControlFreak
34              
35             =cut
36              
37             =head1 SYNOPSIS
38              
39             $con = ControlFreak::Console->new(
40             host => $host,
41             service => $service,
42             full => 1,
43             ctrl => $ctrl,
44             );
45             $con->start;
46              
47             ## return all the current connection handles
48             @hdls = $con->conns;
49              
50             $con->add_conn($hdl);
51              
52             $ok = $con->process_command($string);
53              
54             $con->stop;
55              
56             =head1 METHODS
57              
58             =head2 start
59              
60             Starts the console
61              
62             =cut
63              
64             sub start {
65 1     1 1 11223 my $console = shift;
66 1         4 my %param = @_;
67 1         4 my $ctrl = $console->{ctrl};
68              
69 1         25 my $service = $console->service;
70             my $accept_cb = sub {
71 1     1   2425 my ($fh, $host, $port) = @_;
72 1 50       7 my $addr = $host eq 'unix/'
73             ? "$host:$service"
74             : AnyEvent::Socket::format_hostport($host, $port);
75 1         38 $ctrl->log->info("new connection to admin from $addr");
76 1         227 $console->accept_connection($fh, $host, $port);
77 1         10 };
78              
79             my $prepare_cb = sub {
80 1     1   447 my ($fh, $host, $port) = @_;
81 1         30 $ctrl->log->info("Admin interface started on $host:$port");
82 1 50       653 $param{prepare_cb}->(@_) if $param{prepare_cb};
83 1         7 return 0;
84 1         6 };
85              
86 1         2 $console->{started} = 1;
87 1         178 my $host = $console->host;
88 1         13 my $guard = AnyEvent::Socket::tcp_server
89             $host, $service, $accept_cb, $prepare_cb;
90 1         86 $console->{guard} = $guard;
91 1         10 return 1;
92             }
93              
94             sub accept_connection {
95 1     1 0 3 my $console = shift;
96 1         3 my ($fh, $host, $service) = @_;
97              
98 1         1 my $hdl; $hdl = AnyEvent::Handle->new(
99             fh => $fh,
100             on_eof => sub {
101 0     0   0 $console->{ctrl}->log->info("Console connection: eof");
102 0         0 $hdl->destroy;
103             },
104             on_error => sub {
105 0     0   0 $console->{ctrl}->log->error("Console connection error: $!");
106 0         0 $hdl->destroy;
107             },
108 1         82 );
109 1         100 $console->{handles}{$hdl} = $hdl;
110              
111 1         3 my $get_admin_cmd; $get_admin_cmd = sub {
112 1     1   164 my ($h, $line) = @_;
113 1 50       6 if (lc $line eq 'exit') {
114 0         0 $console->{ctrl}->log->info( "Console exiting" );
115             $h->on_drain(sub {
116 0         0 delete $console->{handles}{$h};
117 0         0 $h->destroy;
118 0         0 });
119 0         0 return 1;
120             }
121              
122             ControlFreak::Command->process(
123             cmd => $line,
124             ctrl => $console->{ctrl},
125             err_cb => sub {
126 0   0     0 my $error = shift || "";
127 0         0 $h->push_write("ERROR: $error$CRLF");
128             },
129             ok_cb => sub {
130 1   50     8 my $out = shift || "";
131 1 50       3 $out .= "\n" if $out;
132 1         7 $h->push_write("${out}OK$CRLF");
133             },
134 1         34 has_priv => $console->full,
135             );
136              
137             ## continue reading
138 1         8 $h->push_read( line => $get_admin_cmd );
139 1         7 };
140              
141 1         5 $hdl->push_read( line => $get_admin_cmd );
142             }
143              
144             =head1 AUTHOR
145              
146             Yann Kerherve
147              
148             =cut
149              
150             "con=console";