Megre pt-agent branch.

This commit is contained in:
Daniel Nichter
2013-06-16 23:23:11 -07:00
64 changed files with 25198 additions and 682 deletions

View File

@@ -9,31 +9,28 @@ BEGIN {
use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use Test::More;
use Time::HiRes qw(sleep);
use File::Temp qw( tempfile );
use File::Temp qw(tempfile);
use Daemon;
use OptionParser;
use PerconaTest;
#plan skip_all => "Hm";
use constant PTDEVDEBUG => $ENV{PTDEVDEBUG} || 0;
my $o = new OptionParser(file => "$trunk/t/lib/samples/daemonizes.pl");
my $d = new Daemon(o=>$o);
my $pid_file = '/tmp/daemonizes.pl.pid';
my $log_file = '/tmp/daemonizes.output';
my $cmd = "$trunk/t/lib/samples/daemonizes.pl";
my $pid_file = "/tmp/pt-daemon-test.pid.$PID";
my $log_file = "/tmp/pt-daemon-test.log.$PID";
sub rm_tmp_files() {
-e $pid_file && (unlink $pid_file || die "Error removing $pid_file");
-e $log_file && (unlink $log_file || die "Error removing $log_file");
-f $pid_file && (unlink $pid_file || die "Error removing $pid_file");
-f $log_file && (unlink $log_file || die "Error removing $log_file");
}
# ############################################################################
# Test that it daemonizes, creates a PID file, and removes that PID file.
# ############################################################################
rm_tmp_files();
my $cmd = "$trunk/t/lib/samples/daemonizes.pl";
my $ret_val = system("$cmd 5 --daemonize --pid $pid_file >/dev/null 2>&1");
die 'Cannot test Daemon.pm because t/daemonizes.pl is not working'
unless $ret_val == 0;
@@ -41,16 +38,34 @@ die 'Cannot test Daemon.pm because t/daemonizes.pl is not working'
PerconaTest::wait_for_files($pid_file);
my $output = `ps wx | grep '$cmd 5' | grep -v grep`;
like($output, qr/$cmd/, 'Daemonizes');
ok(-f $pid_file, 'Creates PID file');
my ($pid) = $output =~ /\s*(\d+)\s+/;
like(
$output,
qr/$cmd/,
'Daemonizes'
);
ok(
-f $pid_file,
'Creates PID file'
);
my ($pid) = $output =~ /^\s*(\d+)\s+/;
$output = slurp_file($pid_file);
is($output, $pid, 'PID file has correct PID');
chomp($output) if $output;
is(
$output,
$pid,
'PID file has correct PID'
);
# Wait until the process goes away
PerconaTest::wait_until(sub { !kill(0, $pid) });
ok(! -f $pid_file, 'Removes PID file upon exit');
ok(
! -f $pid_file,
'Removes PID file upon exit'
);
# ############################################################################
# Check that STDOUT can be redirected
@@ -59,10 +74,19 @@ rm_tmp_files();
system("$cmd 0 --daemonize --log $log_file");
PerconaTest::wait_for_files($log_file);
ok(-f $log_file, 'Log file exists');
ok(
-f $log_file,
'Log file exists'
);
$output = slurp_file($log_file);
like($output, qr/STDOUT\nSTDERR\n/, 'STDOUT and STDERR went to log file');
like(
$output,
qr/STDOUT\nSTDERR\n/,
'STDOUT and STDERR went to log file'
);
my $log_size = -s $log_file;
PTDEVDEBUG && PerconaTest::_d('log size', $log_size);
@@ -71,6 +95,7 @@ PTDEVDEBUG && PerconaTest::_d('log size', $log_size);
system("$cmd 0 --daemonize --log $log_file");
PerconaTest::wait_until(sub { -s $log_file > $log_size });
$output = slurp_file($log_file);
like(
$output,
qr/STDOUT\nSTDERR\nSTDOUT\nSTDERR\n/,
@@ -82,6 +107,7 @@ like(
# ##########################################################################
rm_tmp_files();
diag(`touch $pid_file`);
ok(
-f $pid_file,
'PID file already exists'
@@ -90,7 +116,7 @@ ok(
$output = `$cmd 2 --daemonize --pid $pid_file 2>&1`;
like(
$output,
qr{The PID file $pid_file already exists},
qr{PID file $pid_file exists},
'Dies if PID file already exists'
);
@@ -182,7 +208,7 @@ like(
like(
slurp_file($tempfile),
qr/$pid, is not running/,
qr/Overwriting PID file $pid_file because PID $pid is not running/,
'Says that old PID is not running (issue 419)'
);
@@ -209,54 +235,55 @@ chomp($pid = slurp_file($pid_file));
$output = `$cmd 0 --daemonize --pid $pid_file 2>&1`;
like(
$output,
qr/$pid, is running/,
qr/PID file $pid_file exists and PID $pid is running/,
'Says that PID is running (issue 419)'
);
kill SIGKILL => $pid
if $pid;
if ( $pid ) {
kill 9, $pid;
}
sleep 1;
sleep 0.25;
rm_tmp_files();
# #############################################################################
# Test auto-PID file removal without having to daemonize (for issue 391).
# #############################################################################
my $pid_file2 = "/tmp/pt-daemon-test.pid2.$PID";
{
@ARGV = qw(--pid /tmp/d2.pid);
$o->get_specs("$trunk/t/lib/samples/daemonizes.pl");
$o->get_opts();
my $d2 = new Daemon(o=>$o);
$d2->make_PID_file();
my $d2 = Daemon->new(
pid_file => $pid_file2,
);
$d2->run();
ok(
-f '/tmp/d2.pid',
-f $pid_file2,
'PID file for non-daemon exists'
);
}
# Since $d2 was locally scoped, it should have been destoryed by now.
# This should have caused the PID file to be automatically removed.
ok(
!-f '/tmpo/d2.pid',
!-f $pid_file2,
'PID file auto-removed for non-daemon'
);
# We should still die if the PID file already exists,
# even if we're not a daemon.
{
`touch /tmp/d2.pid`;
@ARGV = qw(--pid /tmp/d2.pid);
$o->get_opts();
diag(`touch $pid_file2`);
eval {
my $d2 = new Daemon(o=>$o); # should die here actually
$d2->make_PID_file();
my $d2 = Daemon->new(
pid_file => $pid_file2,
);
$d2->run();
};
like(
$EVAL_ERROR,
qr{PID file /tmp/d2.pid already exists},
qr/PID file $pid_file2 exists/,
'Dies if PID file already exists for non-daemon'
);
diag(`rm -rf /tmp/d2.pid >/dev/null`);
unlink $pid_file2 if -f $pid_file2;
}
# #############################################################################

View File

@@ -11,7 +11,7 @@ use warnings FATAL => 'all';
use English qw(-no_match_vars);
use Test::More;
use HTTPMicro;
use HTTP::Micro;
local $EVAL_ERROR;
eval { require HTTP::Tiny };
@@ -22,12 +22,12 @@ if ( $EVAL_ERROR ) {
# Need a simple URL that won't try to do chunking.
for my $test_url ( "http://www.percona.com/robots.txt", "https://v.percona.com" ) {
my $tiny = HTTP::Tiny->new(max_redirect => 0)->request('GET', $test_url);
my $micro = HTTPMicro->new->request('GET', $test_url);
my $micro = HTTP::Micro->new->request('GET', $test_url);
like(
$micro->{content},
qr/^\Q$tiny->{content}/,
"HTTPMicro == HTTP::Tiny for $test_url"
"HTTP::Micro == HTTP::Tiny for $test_url"
);
}

View File

@@ -8,10 +8,9 @@ BEGIN {
use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use Test::More;
use IPC::Cmd qw(run can_run);
use PerconaTest;
use Percona::Toolkit;

View File

@@ -0,0 +1,235 @@
#!/usr/bin/env perl
BEGIN {
die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n"
unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH};
unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib";
};
use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use Test::More;
use JSON;
use File::Temp qw(tempdir);
use Percona::Test;
use Percona::Test::Mock::UserAgent;
use Percona::WebAPI::Client;
use Percona::WebAPI::Resource::Agent;
use Percona::WebAPI::Resource::Config;
use Percona::WebAPI::Resource::Service;
use Percona::WebAPI::Resource::Task;
Percona::Toolkit->import(qw(Dumper have_required_args));
Percona::WebAPI::Representation->import(qw(as_json as_hashref));
# #############################################################################
# Create a client with a mock user-agent.
# #############################################################################
my $json = JSON->new;
$json->allow_blessed([]);
$json->convert_blessed([]);
my $ua = Percona::Test::Mock::UserAgent->new(
encode => sub { my $c = shift; return $json->encode($c || {}) },
);
my $client = eval {
Percona::WebAPI::Client->new(
api_key => '123',
ua => $ua,
);
};
is(
$EVAL_ERROR,
'',
'Create client'
) or die;
# #############################################################################
# First thing a client should do is get the entry links.
# #############################################################################
my $return_links = { # what the server returns
agents => '/agents',
};
$ua->{responses}->{get} = [
{
content => {
links => $return_links,
}
},
];
my $links = $client->get(link => $client->entry_link);
is_deeply(
$links,
$return_links,
"Get entry links"
) or diag(Dumper($links));
is_deeply(
$ua->{requests},
[
'GET https://api.tools.percona.com',
],
"1 request, 1 GET"
) or diag(Dumper($ua->{requests}));
# #############################################################################
# Second, a new client will POST an Agent for itself. The entry links
# should have an "agents" link. The server response is empty but the
# URI for the new Agent resource is given by the Location header.
# #############################################################################
my $agent = Percona::WebAPI::Resource::Agent->new(
id => '123',
hostname => 'host',
);
$ua->{responses}->{post} = [
{
headers => { 'Location' => 'agents/5' },
content => '',
},
];
my $uri = $client->post(resources => $agent, link => $links->{agents});
is(
$uri,
"agents/5",
"POST Agent, got Location URI"
);
# #############################################################################
# After successfully creating the new Agent, the client should fetch
# the new Agent resoruce which will have links to the next step: the
# agent's config.
# #############################################################################
$return_links = {
self => 'agents/5',
config => 'agents/5/config',
};
my $content = {
%{ as_hashref($agent) },
links => $return_links,
};
$ua->{responses}->{get} = [
{
headers => { 'X-Percona-Resource-Type' => 'Agent' },
content => $content,
},
];
# Re-using $agent, i.e. updating it with the actual, newly created
# Agent resource as returned by the server with links.
$agent = $client->get(link => $uri);
# Need to use with_links=>1 here because by as_hashref() removes
# links by default because it's usually used to encode and send
# resources, and clients never send links; but here we're using
# it for testing.
is_deeply(
as_hashref($agent, with_links => 1),
$content,
"GET Agent with links"
) or diag(Dumper(as_hashref($agent, with_links => 1)));
# #############################################################################
# Now the agent can get its Config.
# #############################################################################
$return_links = {
self => 'agents/5/config',
services => 'agents/5/services',
};
my $return_config = Percona::WebAPI::Resource::Config->new(
ts => '100',
name => 'Default',
options => {},
links => $return_links,
);
$ua->{responses}->{get} = [
{
headers => { 'X-Percona-Resource-Type' => 'Config' },
content => as_hashref($return_config, with_links => 1),
},
];
my $config = $client->get(link => $agent->links->{config});
is_deeply(
as_hashref($config, with_links => 1),
as_hashref($return_config, with_links => 1),
"GET Config"
) or diag(Dumper(as_hashref($config, with_links => 1)));
# #############################################################################
# Once an agent is configured, i.e. successfully gets a Config resource,
# its Config should have a services link which returns a list of Service
# resources, each with their own links.
# #############################################################################
$return_links = {
'send_data' => '/query-monitor',
};
my $run0 = Percona::WebAPI::Resource::Task->new(
name => 'run-pqd',
number => '0',
program => 'pt-query-digest',
options => '--output json',
output => 'spool',
);
my $svc0 = Percona::WebAPI::Resource::Service->new(
name => 'query-monitor',
run_schedule => '1 * * * *',
spool_schedule => '2 * * * *',
tasks => [ $run0 ],
links => $return_links,
);
$ua->{responses}->{get} = [
{
headers => { 'X-Percona-Resource-Type' => 'Service' },
content => [ as_hashref($svc0, with_links => 1) ],
},
];
my $services = $client->get(link => $config->links->{services});
is(
scalar @$services,
1,
"Got 1 service"
);
is_deeply(
as_hashref($services->[0], with_links => 1),
as_hashref($svc0, with_links => 1),
"GET Services"
) or diag(Dumper(as_hashref($services, with_links => 1)));
is(
$services->[0]->links->{send_data},
"/query-monitor",
"send_data link for Service"
);
# #############################################################################
# Done.
# #############################################################################
done_testing;

View File

@@ -0,0 +1,51 @@
#!/usr/bin/perl
BEGIN {
die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n"
unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH};
unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib";
};
use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use Test::More;
use PerconaTest;
use Percona::Toolkit;
use Percona::WebAPI::Resource::Agent;
use Percona::WebAPI::Resource::Config;
use Percona::WebAPI::Representation;
my $agent = Percona::WebAPI::Resource::Agent->new(
id => '123',
hostname => 'pt',
versions => {
Perl => '5.10.1',
},
);
is(
Percona::WebAPI::Representation::as_json($agent),
q/{"versions":{"Perl":"5.10.1"},"id":"123","hostname":"pt"}/,
"as_json"
);
my $config = Percona::WebAPI::Resource::Config->new(
ts => '100',
name => 'Default',
options => {
'check-interval' => 60,
},
);
is(
Percona::WebAPI::Representation::as_config($config),
"check-interval=60\n",
"as_config"
);
# #############################################################################
# Done.
# #############################################################################
done_testing;

69
t/lib/Safeguards.t Normal file
View File

@@ -0,0 +1,69 @@
#!/usr/bin/perl
BEGIN {
die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n"
unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH};
unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib";
};
use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use Test::More;
use Safeguards;
use Percona::Test;
use Data::Dumper;
$Data::Dumper::Indent = 1;
$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Quotekeys = 0;
my $sample = "t/lib/samples/bash/";
my $safeguards = Safeguards->new(
disk_bytes_free => 104857600,
disk_pct_free => 10,
);
# Filesystem 1024-blocks Used Available Capacity Mounted on
# /dev/disk0s2 118153176 94409664 23487512 81% /
#
# Those values are in Kb, so:
# used = 94409664 (94.4G) = 96_675_495_936 bytes
# free = 23487512 (23.4G) = 24_051_212_288 bytes
# pct free = 100 - 81 = 19 %
my $df = slurp_file("$trunk/$sample/diskspace001.txt");
ok(
$safeguards->check_disk_space(
disk_space => $df,
),
"diskspace001: Enough bytes and pct free"
);
$safeguards = Safeguards->new(
disk_bytes_free => 104857600,
disk_pct_free => 20,
);
ok(
!$safeguards->check_disk_space(
disk_space => $df,
),
"diskspace001: Not enough pct free"
);
$safeguards = Safeguards->new(
disk_bytes_free => 24_051_212_289,
disk_pct_free => 5,
);
ok(
!$safeguards->check_disk_space(
disk_space => $df,
),
"diskspace001: Not enough bytes free"
);
done_testing;

View File

@@ -12,7 +12,9 @@ BEGIN {
use strict;
use warnings FATAL => 'all';
use English qw(-no_match_vars);
use constant PTDEVDEBUG => $ENV{PTDEVDEBUG};
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
use constant PTDEVDEBUG => $ENV{PTDEVDEBUG} || 0;
use Time::HiRes qw(sleep);
@@ -31,22 +33,20 @@ if ( !defined $sleep_time ) {
$o->usage_or_errors();
my $daemon;
if ( $o->get('daemonize') ) {
PTDEVDEBUG && PerconaTest::_d('daemonizing');
my $daemon = Daemon->new(
daemonize => $o->get('daemonize'),
pid_file => $o->get('pid'),
log_file => $o->get('log'),
);
$OUTPUT_AUTOFLUSH = 1;
$daemon->run();
PTDEVDEBUG && PerconaTest::_d('daemonized');
$daemon = new Daemon(o=>$o);
$daemon->daemonize();
PTDEVDEBUG && PerconaTest::_d('daemonized');
print "STDOUT\n";
print STDERR "STDERR\n";
print "STDOUT\n";
print STDERR "STDERR\n";
PTDEVDEBUG && PerconaTest::_d('daemon sleep', $sleep_time);
sleep $sleep_time;
}
PTDEVDEBUG && PerconaTest::_d('daemon sleep', $sleep_time);
sleep $sleep_time;
PTDEVDEBUG && PerconaTest::_d('daemon done');
exit;

File diff suppressed because it is too large Load Diff