We've decided to give up on trying to keep ScanCore, AN::Tools and Striker as three separate things. We had originally hoped to make ScanCore easily separatable from the Anvil!, but this was adding increasing complexity to the project and complexity is the enemy of reliability. In this release, AN::Tools becomes Anvil::Tools, all configuration files move to /etc/anvil and all programs and data files move to /usr/sbin/anvil. Words files are now merged, as are SQL schemas (ScanCore agents will still maintain their own, later). The journald tag has changed from 'an-tools' to 'anvil'. Other changes; * Tools.t has been updated to handle existing tests. New methods and parameters still need to have tests added though. * Added a simple test.pl script used for testing things outside the main program. It will be removed before final release. * Added the simple 'watch_logs' bash script to more easily tail output. Signed-off-by: Digimer <digimer@alteeve.ca>main
parent
ee7b68bfb5
commit
1cb42080c3
33 changed files with 3854 additions and 3727 deletions
@ -1,599 +0,0 @@ |
||||
#!/usr/bin/perl |
||||
|
||||
use strict; |
||||
use warnings; |
||||
use POSIX; |
||||
use Data::Dumper; |
||||
use utf8; |
||||
|
||||
# Be nice and set a version number. |
||||
our $VERSION = "3.0.0"; |
||||
our $THIS_FILE = "Tools.t"; |
||||
|
||||
# Call in the test module, telling it how many tests to expect to run. |
||||
use Test::More tests => 199; |
||||
|
||||
# Load my module via 'use_ok' test. |
||||
BEGIN |
||||
{ |
||||
print "Beginning tests of the AN::Tools suite of modules.\n"; |
||||
use_ok('AN::Tools', 3.0.0); |
||||
} |
||||
|
||||
### Core tests |
||||
my $an = AN::Tools->new(); |
||||
like($an, qr/^AN::Tools=HASH\(0x\w+\)$/, "Verifying that AN::Tools object is valid."); |
||||
like($an->data, qr/^HASH\(0x\w+\)$/, "Verifying that 'data' is a hash reference."); |
||||
is($an->environment, "cli", "Verifying that environment initially reports 'cli'."); |
||||
$an->environment('html'); |
||||
is($an->environment, "html", "Verifying that environment was properly set to 'html'."); |
||||
$an->environment('cli'); |
||||
is($an->environment, "cli", "Verifying that environment was properly reset back to 'cli'."); |
||||
|
||||
# Test handles to child modules. |
||||
like($an->Alert, qr/^AN::Tools::Alert=HASH\(0x\w+\)$/, "Verifying that 'Alert' is a handle to AN::Tools::Alert."); |
||||
like($an->Convert, qr/^AN::Tools::Convert=HASH\(0x\w+\)$/, "Verifying that 'Convert' is a handle to AN::Tools::Convert."); |
||||
like($an->Database, qr/^AN::Tools::Database=HASH\(0x\w+\)$/, "Verifying that 'Database' is a handle to AN::Tools::Database."); |
||||
like($an->Get, qr/^AN::Tools::Get=HASH\(0x\w+\)$/, "Verifying that 'Get' is a handle to AN::Tools::Get."); |
||||
like($an->Log, qr/^AN::Tools::Log=HASH\(0x\w+\)$/, "Verifying that 'Log' is a handle to AN::Tools::Log."); |
||||
like($an->Storage, qr/^AN::Tools::Storage=HASH\(0x\w+\)$/, "Verifying that 'Storage' is a handle to AN::Tools::Storage."); |
||||
like($an->System, qr/^AN::Tools::System=HASH\(0x\w+\)$/, "Verifying that 'System' is a handle to AN::Tools::System."); |
||||
like($an->Template, qr/^AN::Tools::Template=HASH\(0x\w+\)$/, "Verifying that 'Template' is a handle to AN::Tools::Template."); |
||||
like($an->Validate, qr/^AN::Tools::Validate=HASH\(0x\w+\)$/, "Verifying that 'Validate' is a handle to AN::Tools::Validate."); |
||||
like($an->Words, qr/^AN::Tools::Words=HASH\(0x\w+\)$/, "Verifying that 'Words' is a handle to AN::Tools::Words."); |
||||
|
||||
### Special |
||||
# We log a note telling the user to ignore log entries caused by this test suite. We'll then read it back and |
||||
# make sure it logged properly |
||||
$an->Log->entry({level => 0, priority => "alert", key => "log_0048"}); |
||||
my $message = $an->Words->string({key => "log_0048"}); |
||||
my $last_log = $an->System->call({shell_call => $an->data->{path}{exe}{journalctl}." -t an-tools --lines 1 --full --output cat --no-pager"}); |
||||
is($last_log, $message, "Verified that we could write a log entry to journalctl by warning the user of incoming warnings and errors."); |
||||
|
||||
### AN::Tools::Alert tests |
||||
# <none yet> |
||||
|
||||
### AN::Tools::Convert tests |
||||
# cidr tests |
||||
is($an->Convert->cidr({cidr => "fake"}), "", "Verifying that Convert->cidr properly returned an empty string for a bad 'cidr' parameter."); |
||||
is($an->Convert->cidr({cidr => "0"}), "0.0.0.0", "Verifying that Convert->cidr properly returned '0.0.0.0' when given a 'cidr' parameter of '0'."); |
||||
is($an->Convert->cidr({cidr => "1"}), "128.0.0.0", "Verifying that Convert->cidr properly returned '128.0.0.0' when given a 'cidr' parameter of '1'."); |
||||
is($an->Convert->cidr({cidr => "2"}), "192.0.0.0", "Verifying that Convert->cidr properly returned '192.0.0.0' when given a 'cidr' parameter of '2'."); |
||||
is($an->Convert->cidr({cidr => "3"}), "224.0.0.0", "Verifying that Convert->cidr properly returned '224.0.0.0' when given a 'cidr' parameter of '3'."); |
||||
is($an->Convert->cidr({cidr => "4"}), "240.0.0.0", "Verifying that Convert->cidr properly returned '240.0.0.0' when given a 'cidr' parameter of '4'."); |
||||
is($an->Convert->cidr({cidr => "5"}), "248.0.0.0", "Verifying that Convert->cidr properly returned '248.0.0.0' when given a 'cidr' parameter of '5'."); |
||||
is($an->Convert->cidr({cidr => "6"}), "252.0.0.0", "Verifying that Convert->cidr properly returned '252.0.0.0' when given a 'cidr' parameter of '6'."); |
||||
is($an->Convert->cidr({cidr => "7"}), "254.0.0.0", "Verifying that Convert->cidr properly returned '254.0.0.0' when given a 'cidr' parameter of '7'."); |
||||
is($an->Convert->cidr({cidr => "8"}), "255.0.0.0", "Verifying that Convert->cidr properly returned '255.0.0.0' when given a 'cidr' parameter of '8'."); |
||||
is($an->Convert->cidr({cidr => "9"}), "255.128.0.0", "Verifying that Convert->cidr properly returned '255.128.0.0' when given a 'cidr' parameter of '9'."); |
||||
is($an->Convert->cidr({cidr => "10"}), "255.192.0.0", "Verifying that Convert->cidr properly returned '255.192.0.0' when given a 'cidr' parameter of '10'."); |
||||
is($an->Convert->cidr({cidr => "11"}), "255.224.0.0", "Verifying that Convert->cidr properly returned '255.224.0.0' when given a 'cidr' parameter of '11'."); |
||||
is($an->Convert->cidr({cidr => "12"}), "255.240.0.0", "Verifying that Convert->cidr properly returned '255.240.0.0' when given a 'cidr' parameter of '12'."); |
||||
is($an->Convert->cidr({cidr => "13"}), "255.248.0.0", "Verifying that Convert->cidr properly returned '255.248.0.0' when given a 'cidr' parameter of '13'."); |
||||
is($an->Convert->cidr({cidr => "14"}), "255.252.0.0", "Verifying that Convert->cidr properly returned '255.252.0.0' when given a 'cidr' parameter of '14'."); |
||||
is($an->Convert->cidr({cidr => "15"}), "255.254.0.0", "Verifying that Convert->cidr properly returned '255.254.0.0' when given a 'cidr' parameter of '15'."); |
||||
is($an->Convert->cidr({cidr => "16"}), "255.255.0.0", "Verifying that Convert->cidr properly returned '255.255.0.0' when given a 'cidr' parameter of '16'."); |
||||
is($an->Convert->cidr({cidr => "17"}), "255.255.128.0", "Verifying that Convert->cidr properly returned '255.255.128.0' when given a 'cidr' parameter of '17'."); |
||||
is($an->Convert->cidr({cidr => "18"}), "255.255.192.0", "Verifying that Convert->cidr properly returned '255.255.192.0' when given a 'cidr' parameter of '18'."); |
||||
is($an->Convert->cidr({cidr => "19"}), "255.255.224.0", "Verifying that Convert->cidr properly returned '255.255.224.0' when given a 'cidr' parameter of '19'."); |
||||
is($an->Convert->cidr({cidr => "20"}), "255.255.240.0", "Verifying that Convert->cidr properly returned '255.255.240.0' when given a 'cidr' parameter of '20'."); |
||||
is($an->Convert->cidr({cidr => "21"}), "255.255.248.0", "Verifying that Convert->cidr properly returned '255.255.248.0' when given a 'cidr' parameter of '21'."); |
||||
is($an->Convert->cidr({cidr => "22"}), "255.255.252.0", "Verifying that Convert->cidr properly returned '255.255.252.0' when given a 'cidr' parameter of '22'."); |
||||
is($an->Convert->cidr({cidr => "23"}), "255.255.254.0", "Verifying that Convert->cidr properly returned '255.255.254.0' when given a 'cidr' parameter of '23'."); |
||||
is($an->Convert->cidr({cidr => "24"}), "255.255.255.0", "Verifying that Convert->cidr properly returned '255.255.255.0' when given a 'cidr' parameter of '24'."); |
||||
is($an->Convert->cidr({cidr => "25"}), "255.255.255.128", "Verifying that Convert->cidr properly returned '255.255.255.128' when given a 'cidr' parameter of '25'."); |
||||
is($an->Convert->cidr({cidr => "26"}), "255.255.255.192", "Verifying that Convert->cidr properly returned '255.255.255.192' when given a 'cidr' parameter of '26'."); |
||||
is($an->Convert->cidr({cidr => "27"}), "255.255.255.224", "Verifying that Convert->cidr properly returned '255.255.255.224' when given a 'cidr' parameter of '27'."); |
||||
is($an->Convert->cidr({cidr => "28"}), "255.255.255.240", "Verifying that Convert->cidr properly returned '255.255.255.240' when given a 'cidr' parameter of '28'."); |
||||
is($an->Convert->cidr({cidr => "29"}), "255.255.255.248", "Verifying that Convert->cidr properly returned '255.255.255.248' when given a 'cidr' parameter of '29'."); |
||||
is($an->Convert->cidr({cidr => "30"}), "255.255.255.252", "Verifying that Convert->cidr properly returned '255.255.255.252' when given a 'cidr' parameter of '30'."); |
||||
is($an->Convert->cidr({cidr => "31"}), "255.255.255.254", "Verifying that Convert->cidr properly returned '255.255.255.254' when given a 'cidr' parameter of '31'."); |
||||
is($an->Convert->cidr({cidr => "32"}), "255.255.255.255", "Verifying that Convert->cidr properly returned '255.255.255.255' when given a 'cidr' parameter of '32'."); |
||||
is($an->Convert->cidr({subnet => "fake"}), "", "Verifying that Convert->cidr properly returned an empty string for a bad 'subnet' parameter."); |
||||
is($an->Convert->cidr({subnet => "0.0.0.0"}), "0", "Verifying that Convert->cidr properly returned '0' when given a 'subnet' parameter of '0.0.0.0'."); |
||||
is($an->Convert->cidr({subnet => "128.0.0.0"}), "1", "Verifying that Convert->cidr properly returned '1' when given a 'subnet' parameter of '128.0.0.0'."); |
||||
is($an->Convert->cidr({subnet => "192.0.0.0"}), "2", "Verifying that Convert->cidr properly returned '2' when given a 'subnet' parameter of '192.0.0.0'."); |
||||
is($an->Convert->cidr({subnet => "224.0.0.0"}), "3", "Verifying that Convert->cidr properly returned '3' when given a 'subnet' parameter of '224.0.0.0'."); |
||||
is($an->Convert->cidr({subnet => "240.0.0.0"}), "4", "Verifying that Convert->cidr properly returned '4' when given a 'subnet' parameter of '240.0.0.0'."); |
||||
is($an->Convert->cidr({subnet => "248.0.0.0"}), "5", "Verifying that Convert->cidr properly returned '5' when given a 'subnet' parameter of '248.0.0.0'."); |
||||
is($an->Convert->cidr({subnet => "252.0.0.0"}), "6", "Verifying that Convert->cidr properly returned '6' when given a 'subnet' parameter of '252.0.0.0'."); |
||||
is($an->Convert->cidr({subnet => "254.0.0.0"}), "7", "Verifying that Convert->cidr properly returned '7' when given a 'subnet' parameter of '254.0.0.0'."); |
||||
is($an->Convert->cidr({subnet => "255.0.0.0"}), "8", "Verifying that Convert->cidr properly returned '8' when given a 'subnet' parameter of '255.0.0.0'."); |
||||
is($an->Convert->cidr({subnet => "255.128.0.0"}), "9", "Verifying that Convert->cidr properly returned '9' when given a 'subnet' parameter of '255.128.0.0'."); |
||||
is($an->Convert->cidr({subnet => "255.192.0.0"}), "10", "Verifying that Convert->cidr properly returned '10' when given a 'subnet' parameter of '255.192.0.0'."); |
||||
is($an->Convert->cidr({subnet => "255.224.0.0"}), "11", "Verifying that Convert->cidr properly returned '11' when given a 'subnet' parameter of '255.224.0.0'."); |
||||
is($an->Convert->cidr({subnet => "255.240.0.0"}), "12", "Verifying that Convert->cidr properly returned '12' when given a 'subnet' parameter of '255.240.0.0'."); |
||||
is($an->Convert->cidr({subnet => "255.248.0.0"}), "13", "Verifying that Convert->cidr properly returned '13' when given a 'subnet' parameter of '255.248.0.0'."); |
||||
is($an->Convert->cidr({subnet => "255.252.0.0"}), "14", "Verifying that Convert->cidr properly returned '14' when given a 'subnet' parameter of '255.252.0.0'."); |
||||
is($an->Convert->cidr({subnet => "255.254.0.0"}), "15", "Verifying that Convert->cidr properly returned '15' when given a 'subnet' parameter of '255.254.0.0'."); |
||||
is($an->Convert->cidr({subnet => "255.255.0.0"}), "16", "Verifying that Convert->cidr properly returned '16' when given a 'subnet' parameter of '255.255.0.0'."); |
||||
is($an->Convert->cidr({subnet => "255.255.128.0"}), "17", "Verifying that Convert->cidr properly returned '17' when given a 'subnet' parameter of '255.255.128.0'."); |
||||
is($an->Convert->cidr({subnet => "255.255.192.0"}), "18", "Verifying that Convert->cidr properly returned '18' when given a 'subnet' parameter of '255.255.192.0'."); |
||||
is($an->Convert->cidr({subnet => "255.255.224.0"}), "19", "Verifying that Convert->cidr properly returned '19' when given a 'subnet' parameter of '255.255.224.0'."); |
||||
is($an->Convert->cidr({subnet => "255.255.240.0"}), "20", "Verifying that Convert->cidr properly returned '20' when given a 'subnet' parameter of '255.255.240.0'."); |
||||
is($an->Convert->cidr({subnet => "255.255.248.0"}), "21", "Verifying that Convert->cidr properly returned '21' when given a 'subnet' parameter of '255.255.248.0'."); |
||||
is($an->Convert->cidr({subnet => "255.255.252.0"}), "22", "Verifying that Convert->cidr properly returned '22' when given a 'subnet' parameter of '255.255.252.0'."); |
||||
is($an->Convert->cidr({subnet => "255.255.254.0"}), "23", "Verifying that Convert->cidr properly returned '23' when given a 'subnet' parameter of '255.255.254.0'."); |
||||
is($an->Convert->cidr({subnet => "255.255.255.0"}), "24", "Verifying that Convert->cidr properly returned '24' when given a 'subnet' parameter of '255.255.255.0'."); |
||||
is($an->Convert->cidr({subnet => "255.255.255.128"}), "25", "Verifying that Convert->cidr properly returned '25' when given a 'subnet' parameter of '255.255.255.128'."); |
||||
is($an->Convert->cidr({subnet => "255.255.255.192"}), "26", "Verifying that Convert->cidr properly returned '26' when given a 'subnet' parameter of '255.255.255.192'."); |
||||
is($an->Convert->cidr({subnet => "255.255.255.224"}), "27", "Verifying that Convert->cidr properly returned '27' when given a 'subnet' parameter of '255.255.255.224'."); |
||||
is($an->Convert->cidr({subnet => "255.255.255.240"}), "28", "Verifying that Convert->cidr properly returned '28' when given a 'subnet' parameter of '255.255.255.240'."); |
||||
is($an->Convert->cidr({subnet => "255.255.255.248"}), "29", "Verifying that Convert->cidr properly returned '29' when given a 'subnet' parameter of '255.255.255.248'."); |
||||
is($an->Convert->cidr({subnet => "255.255.255.252"}), "30", "Verifying that Convert->cidr properly returned '30' when given a 'subnet' parameter of '255.255.255.252'."); |
||||
is($an->Convert->cidr({subnet => "255.255.255.254"}), "31", "Verifying that Convert->cidr properly returned '31' when given a 'subnet' parameter of '255.255.255.254'."); |
||||
is($an->Convert->cidr({subnet => "255.255.255.255"}), "32", "Verifying that Convert->cidr properly returned '32' when given a 'subnet' parameter of '255.255.255.255'."); |
||||
|
||||
### AN::Tools::Database tests |
||||
# <none yet> |
||||
|
||||
### AN::Tools::Get tests |
||||
# date_and_time |
||||
like($an->Get->date_and_time(), qr/^\d\d\d\d\/\d\d\/\d\d \d\d:\d\d:\d\d$/, "Verifying the current date and time is returned."); |
||||
like($an->Get->date_and_time({date_only => 1}), qr/^\d\d\d\d\/\d\d\/\d\d$/, "Verifying the current date alone is returned."); |
||||
like($an->Get->date_and_time({time_only => 1}), qr/^\d\d:\d\d:\d\d$/, "Verifying the current time alone is returned."); |
||||
like($an->Get->date_and_time({file_name => 1}), qr/^\d\d\d\d-\d\d-\d\d_\d\d-\d\d-\d\d$/, "Verifying the current date and time is returned in a file-friendly format."); |
||||
like($an->Get->date_and_time({file_name => 1, date_only => 1}), qr/^\d\d\d\d-\d\d-\d\d$/, "Verifying the current date only is returned in a file-friendly format."); |
||||
like($an->Get->date_and_time({file_name => 1, time_only => 1}), qr/^\d\d-\d\d-\d\d$/, "Verifying the current time only is returned in a file-friendly format."); |
||||
# We can't be too specific because the user's TZ will shift the results |
||||
like($an->Get->date_and_time({use_time => 1234567890}), qr/2009\/02\/1[34] \d\d:\d\d:\d\d$/, "Verified that a specific unixtime returned the expected date."); |
||||
like($an->Get->date_and_time({use_time => 1234567890, offset => 31536000}), qr/2010\/02\/1[34] \d\d:\d\d:\d\d$/, "Verified that a specific unixtime with a one year in the future offset returned the expected date."); |
||||
like($an->Get->date_and_time({use_time => 1234567890, offset => -31536000}), qr/2008\/02\/1[34] \d\d:\d\d:\d\d$/, "Verified that a specific unixtime with a one year in the past offset returned the expected date."); |
||||
# host_uuid |
||||
like($an->Get->host_uuid, qr/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/, "Verifying ability to read host uuid."); |
||||
### TODO: How to test Get->switches? |
||||
# uuid |
||||
like($an->Get->uuid, qr/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/, "Verifying ability to generate a random uuid."); |
||||
|
||||
### AN::Tools::Log tests |
||||
# entry is tested at the start of this test suite. |
||||
# language |
||||
is($an->Log->language, "en_CA", "Verifying the default log language is 'en_CA'."); |
||||
$an->Log->language({set => "jp"}); |
||||
is($an->Log->language, "jp", "Verifying the log language was changed to 'jp'."); |
||||
$an->Log->language({set => "en_CA"}); |
||||
is($an->Log->language, "en_CA", "Verifying the log language is back to 'en_CA'."); |
||||
|
||||
# log_level |
||||
is($an->Log->level, "1", "Verifying the default log level is '1'."); |
||||
$an->Log->level({set => 0}); |
||||
is($an->Log->level, "0", "Verifying the log level changed to '0'."); |
||||
$an->Log->level({set => 1}); |
||||
is($an->Log->level, "1", "Verifying the log level changed to '1'."); |
||||
$an->Log->level({set => 2}); |
||||
is($an->Log->level, "2", "Verifying the log level changed to '2'."); |
||||
$an->Log->level({set => 3}); |
||||
is($an->Log->level, "3", "Verifying the log level changed to '3'."); |
||||
$an->Log->level({set => 4}); |
||||
is($an->Log->level, "4", "Verifying the log level changed to '4'."); |
||||
$an->Log->level({set => "foo"}); |
||||
is($an->Log->level, "4", "Verifying the log level stayed at '4' with bad input."); |
||||
$an->Log->level({set => 1}); |
||||
is($an->Log->level, "1", "Verifying the log level changed back to '1'."); |
||||
# secure |
||||
is($an->Log->secure, "0", "Verifying that logging secure messages is disabled by default."); |
||||
$an->Log->secure({set => "foo"}); |
||||
is($an->Log->secure, "0", "Verifying that logging secure messages stayed disabled on bad input."); |
||||
$an->Log->secure({set => 1}); |
||||
is($an->Log->secure, "1", "Verifying that logging secure messages was enabled."); |
||||
$an->Log->secure({set => 0}); |
||||
is($an->Log->secure, "0", "Verifying that logging secure messages was disabled again."); |
||||
# variables |
||||
$an->Log->variables({level => 0, list => { a => "1" }}); |
||||
my $list_a = $an->System->call({shell_call => $an->data->{path}{exe}{journalctl}." -t an-tools --lines 1 --full --output cat --no-pager"}); |
||||
is($list_a, "a: [1]", "Verified that we could log a list of variables (1 entry)."); |
||||
$an->Log->variables({level => 0, list => { a => "1", b => "2" }}); |
||||
my $list_b = $an->System->call({shell_call => $an->data->{path}{exe}{journalctl}." -t an-tools --lines 1 --full --output cat --no-pager"}); |
||||
is($list_b, "a: [1], b: [2]", "Verified that we could log a list of variables (2 entries)."); |
||||
$an->Log->variables({level => 0, list => { a => "1", b => "2", c => "3" }}); |
||||
my $list_c = $an->System->call({shell_call => $an->data->{path}{exe}{journalctl}." -t an-tools --lines 1 --full --output cat --no-pager"}); |
||||
is($list_c, "a: [1], b: [2], c: [3]", "Verified that we could log a list of variables (3 entries)."); |
||||
$an->Log->variables({level => 0, list => { a => "1", b => "2", c => "3", d => "4" }}); |
||||
my $list_d = $an->System->call({shell_call => $an->data->{path}{exe}{journalctl}." -t an-tools --lines 1 --full --output cat --no-pager"}); |
||||
is($list_d, "a: [1], b: [2], c: [3], d: [4]", "Verified that we could log a list of variables (4 entries)."); |
||||
$an->Log->variables({level => 0, list => { a => "1", b => "2", c => "3", d => "4", e => "5" }}); |
||||
my $list_e = $an->System->call({shell_call => $an->data->{path}{exe}{journalctl}." -t an-tools --lines 1 --full --output cat --no-pager"}); |
||||
my $say_variables = $an->Words->key({key => "log_0019"}); |
||||
my $expect_e = "$say_variables |
||||
|- a: [1] |
||||
|- b: [2] |
||||
|- c: [3] |
||||
|- d: [4] |
||||
\\- e: [5]"; |
||||
is($list_e, $expect_e, "Verified that we could log a list of variables (5 entries, line wrapping)."); |
||||
# _adjust_log_level - We're simulating switches to test Log->_adjust_log_level |
||||
$an->data->{switches}{V} = "#!set!#"; |
||||
$an->data->{switches}{v} = ""; |
||||
$an->data->{switches}{vv} = ""; |
||||
$an->data->{switches}{vvv} = ""; |
||||
$an->data->{switches}{vvvv} = ""; |
||||
$an->Log->_adjust_log_level; |
||||
is($an->Log->level, "0", "Verifying the log level was set to '0' with Log->_adjust_log_leve() with 'V' switch set."); |
||||
$an->data->{switches}{V} = ""; |
||||
$an->data->{switches}{v} = "#!set!#"; |
||||
$an->Log->_adjust_log_level; |
||||
is($an->Log->level, "1", "Verifying the log level was set to '1' with Log->_adjust_log_leve() with 'v' switch set."); |
||||
$an->data->{switches}{v} = ""; |
||||
$an->data->{switches}{vv} = "#!set!#"; |
||||
$an->Log->_adjust_log_level; |
||||
is($an->Log->level, "2", "Verifying the log level was set to '2' with Log->_adjust_log_leve() with 'vv' switch set."); |
||||
$an->data->{switches}{vv} = ""; |
||||
$an->data->{switches}{vvv} = "#!set!#"; |
||||
$an->Log->_adjust_log_level; |
||||
is($an->Log->level, "3", "Verifying the log level was set to '3' with Log->_adjust_log_leve() with 'vvv' switch set."); |
||||
$an->data->{switches}{vvv} = ""; |
||||
$an->data->{switches}{vvvv} = "#!set!#"; |
||||
$an->Log->_adjust_log_level; |
||||
is($an->Log->level, "4", "Verifying the log level was set to '4' with Log->_adjust_log_leve() with 'vvvv' switch set."); |
||||
$an->data->{switches}{vvvv} = ""; |
||||
$an->data->{switches}{v} = "#!set!#"; |
||||
$an->Log->_adjust_log_level; |
||||
is($an->Log->level, "1", "Verifying the log level was set back to '1' with Log->_adjust_log_leve() with 'v' switch set."); |
||||
|
||||
### AN::Tools::Storage tests - These happen a little out of order. |
||||
# We need to pick a user name and group name to use for these tests. So we'll start by reading in passwd. |
||||
my $passwd = $an->Storage->read_file({file => "/etc/passwd"}); |
||||
my $group = $an->Storage->read_file({file => "/etc/group"}); |
||||
my $read_ok = 0; |
||||
my $use_user = ""; |
||||
my $use_group = ""; |
||||
foreach my $line (split/\n/, $passwd) |
||||
{ |
||||
if ($line =~ /^root:/) |
||||
{ |
||||
$read_ok = 1; |
||||
} |
||||
elsif ($line =~ /^(\w+):x:\d/) |
||||
{ |
||||
$use_user = $1; |
||||
last; |
||||
} |
||||
} |
||||
foreach my $line (split/\n/, $group) |
||||
{ |
||||
if ($line =~ /^root:/) |
||||
{ |
||||
# skip |
||||
} |
||||
elsif ($line =~ /^(\w+):x:\d/) |
||||
{ |
||||
$use_group = $1; |
||||
last; |
||||
} |
||||
} |
||||
# print "[ Debug ] - Using the user: [$use_user] and the group: [$use_group] for testing.\n"; |
||||
is($read_ok, "1", "Verified that 'Storage->read_file' could read a file."); |
||||
# Write a file /tmp/foo |
||||
my $body = "This is a test file created as part of the AN::Tools test suite.\nYou can safely delete it if you wish.\n"; |
||||
my $test_file = "/tmp/an-tools.test"; |
||||
if (-e $test_file) |
||||
{ |
||||
# remove the old test file. |
||||
unlink $test_file or die "The test file: [$test_file] exists (from a previous run?) and can't be removed. The error was: $!\n"; |
||||
} |
||||
$an->Storage->write_file({body => $body, file => $test_file, group => $use_group, user => $use_user, mode => "0666"}); |
||||
my $write_ok = 0; |
||||
if (-e $test_file) |
||||
{ |
||||
$write_ok = 1; |
||||
} |
||||
is($write_ok, "1", "Verifying that 'Storage->write_file' could write a file (tested writing to: [$test_file])."); |
||||
my $mode = $an->Storage->read_mode({target => $test_file}); |
||||
my ($uid, $gid) = (stat($test_file))[4,5]; |
||||
my $file_user_name = getpwuid($uid); |
||||
my $file_group_name = getgrgid($gid); |
||||
#print "[ Debug ] - test_file: [$test_file], mode: [$mode], owning user: [$file_user_name ($uid)], owning group: [$file_group_name ($gid)]\n"; |
||||
is($mode, "0666", "Verifying that 'Storage->write_file' set the mode correctly when writing a file."); |
||||
is($file_user_name, $use_user, "Verifying that 'Storage->write_file' set the user name properly when the file was written."); |
||||
is($file_group_name, $use_group, "Verifying that 'Storage->write_file' set the group name properly when the file was written."); |
||||
# change_mode |
||||
$an->Storage->change_mode({target => $test_file, mode => "4755"}); |
||||
$mode = $an->Storage->read_mode({target => $test_file}); |
||||
is($mode, "4755", "Verifying that 'Storage->change_mode' was able to change the mode of the test file (including setting the setuid and setgid sticky bits)."); |
||||
$an->Storage->change_mode({target => $test_file, mode => "644"}); |
||||
$mode = $an->Storage->read_mode({target => $test_file}); |
||||
is($mode, "0644", "Verifying that 'Storage->change_mode' was able to change the mode of the test file using three digits instead of four."); |
||||
# change_owner |
||||
$an->Storage->change_owner({target => $test_file, user => 0}); |
||||
$file_user_name = ""; |
||||
$file_group_name = ""; |
||||
($uid, $gid) = (stat($test_file))[4,5]; |
||||
$file_user_name = getpwuid($uid); |
||||
$file_group_name = getgrgid($gid); |
||||
is($file_user_name, "root", "Verifying that 'Storage->change_user', when passed only a user ID, changed the user."); |
||||
is($file_group_name, $use_group, "Verifying that 'Storage->change_user', when passed only a user ID, did not change the group."); |
||||
$an->Storage->change_owner({target => $test_file, user => $use_user}); |
||||
$file_user_name = ""; |
||||
$file_group_name = ""; |
||||
($uid, $gid) = (stat($test_file))[4,5]; |
||||
$file_user_name = getpwuid($uid); |
||||
$file_group_name = getgrgid($gid); |
||||
is($file_user_name, $use_user, "Verifying that 'Storage->change_user', when passed only a user name, changed the user."); |
||||
is($file_group_name, $use_group, "Verifying that 'Storage->change_user', when passed only a user ID, did not change the group."); |
||||
$an->Storage->change_owner({target => $test_file, group => 0}); |
||||
$file_user_name = ""; |
||||
$file_group_name = ""; |
||||
($uid, $gid) = (stat($test_file))[4,5]; |
||||
$file_user_name = getpwuid($uid); |
||||
$file_group_name = getgrgid($gid); |
||||
is($file_user_name, $use_user, "Verifying that 'Storage->change_user', when passed only a group ID, did not change the user."); |
||||
is($file_group_name, "root", "Verifying that 'Storage->change_user', when passed only a group ID, changed the group."); |
||||
$an->Storage->change_owner({target => $test_file, group => $use_group}); |
||||
$file_user_name = ""; |
||||
$file_group_name = ""; |
||||
($uid, $gid) = (stat($test_file))[4,5]; |
||||
$file_user_name = getpwuid($uid); |
||||
$file_group_name = getgrgid($gid); |
||||
is($file_user_name, $use_user, "Verifying that 'Storage->change_user', when passed only a group name, did not change the user."); |
||||
is($file_group_name, $use_group, "Verifying that 'Storage->change_user', when passed only a group name, changed the group."); |
||||
$an->Storage->change_owner({target => $test_file, user => "root", group => "root"}); |
||||
$file_user_name = ""; |
||||
$file_group_name = ""; |
||||
($uid, $gid) = (stat($test_file))[4,5]; |
||||
$file_user_name = getpwuid($uid); |
||||
$file_group_name = getgrgid($gid); |
||||
is($file_user_name, "root", "Verifying that 'Storage->change_user', when passed both a user and group name, changed the user."); |
||||
is($file_group_name, "root", "Verifying that 'Storage->change_user', when passed both a user and group name, changed the group."); |
||||
my $change_owner_rc = $an->Storage->change_owner({target => "", user => "root", group => "root"}); |
||||
is($change_owner_rc, "1", "Verifying that 'Storage->change_user', when passed no target, returned '1'."); |
||||
$change_owner_rc = ""; |
||||
$change_owner_rc = $an->Storage->change_owner({target => "/fake/file", user => "root", group => "root"}); |
||||
is($change_owner_rc, "1", "Verifying that 'Storage->change_user', when passed a bad file, returned '1'."); |
||||
# copy_file |
||||
my $copy_file = "/tmp/an-tools.copy"; |
||||
my $copied_ok = 0; |
||||
if (-e $copy_file) |
||||
{ |
||||
unlink $copy_file or die "The test copy file: [$copy_file] exists (from a previous run?) and can't be removed. The error was: $!\n"; |
||||
} |
||||
$an->Storage->copy_file({source => $test_file, target => $copy_file}); |
||||
if (-e $copy_file) |
||||
{ |
||||
$copied_ok = 1; |
||||
} |
||||
is($copied_ok, "1", "Verifying that 'Storage->copy_file' was able to copy the test file."); |
||||
my $copy_rc = $an->Storage->copy_file({target => $copy_file}); |
||||
is($copy_rc, "1", "Verifying that 'Storage->copy_file' returned '1' when no source file was passed."); |
||||
$copy_rc = ""; |
||||
$copy_rc = $an->Storage->copy_file({source => $test_file}); |
||||
is($copy_rc, "2", "Verifying that 'Storage->copy_file' returned '2' when no target file was passed."); |
||||
$copy_rc = ""; |
||||
$copy_rc = $an->Storage->copy_file({source => $test_file, target => $copy_file}); |
||||
is($copy_rc, "3", "Verifying that 'Storage->copy_file' returned '3' when the target file already exists."); |
||||
$copy_rc = ""; |
||||
$copy_rc = $an->Storage->copy_file({source => $test_file, target => $copy_file, overwrite => 1}); |
||||
is($copy_rc, "0", "Verifying that 'Storage->copy_file' returned '0' when the target file already exists and overwrite was set."); |
||||
$copy_rc = ""; |
||||
$copy_rc = $an->Storage->copy_file({source => "/fake/file", target => $copy_file}); |
||||
is($copy_rc, "4", "Verifying that 'Storage->copy_file' returned '4' when the target file is passed but doesn't exist."); |
||||
# find |
||||
my $test_path = $an->Storage->find({ file => "AN/Tools.t" }); |
||||
is($test_path, "/usr/share/perl5/AN/Tools.t", "Verifying that Storage->find successfully found 'AN/Tools.t'."); |
||||
my $bad_path = $an->Storage->find({ file => "AN/wa.t" }); |
||||
is($bad_path, "#!not_found!#", "Verifying that Storage->find properly returned '#!not_found!#' for a non-existed file."); |
||||
# make_directory |
||||
my $test_directory = "/tmp/an-tools/test/directory"; |
||||
if (-d $test_directory) |
||||
{ |
||||
foreach my $this_directory ("/tmp/an-tools/test/directory", "/tmp/an-tools/test", "/tmp/an-tools") |
||||
{ |
||||
rmdir $this_directory or die "Failed to remove the test directory: [$this_directory] (from a previous test?). The error was: $!\n"; |
||||
} |
||||
} |
||||
# This uses an odd mode on purpose |
||||
$an->Storage->make_directory({directory => $test_directory, group => $use_group, user => $use_user, mode => "0757"}); |
||||
my $created_directory = 0; |
||||
if (-d $test_directory) |
||||
{ |
||||
$created_directory = 1; |
||||
} |
||||
is($created_directory, "1", "Verifying that 'Storage->create_directory' created a directory and its parents."); |
||||
my $directory_mode = $an->Storage->read_mode({target => $test_directory}); |
||||
($uid, $gid) = (stat($test_directory))[4,5]; |
||||
my $directory_user_name = getpwuid($uid); |
||||
my $directory_group_name = getgrgid($gid); |
||||
is($directory_mode, "0757", "Verifying that 'Storage->create_directory' created a directory with the requested mode."); |
||||
is($directory_user_name, $use_user, "Verifying that 'Storage->create_directory' created a directory with the requested owner."); |
||||
is($directory_group_name, $use_group, "Verifying that 'Storage->create_directory' created a directory with the requested group."); |
||||
# read_config |
||||
$an->data->{foo}{bar}{a} = "test"; |
||||
is($an->Storage->read_config({ file => "AN/test.conf" }), 0, "Verifying that 'Storage->read_config' successfully found 'AN/test.conf'."); |
||||
is($an->Storage->read_config({ file => "" }), 1, "Verifying that 'Storage->read_config' returns '1' when called without a 'file' parameter being set."); |
||||
is($an->Storage->read_config({ file => "AN/moo.conf" }), 2, "Verifying that 'Storage->read_config' returns '2' when the non-existent 'AN/moo.conf' is passed."); |
||||
cmp_ok($an->data->{foo}{bar}{a}, 'eq', 'I am "a"', "Verifying that 'AN/test.conf's 'foo::bar::a' overwrote an earlier set value."); |
||||
cmp_ok($an->data->{foo}{bar}{b}, 'eq', 'I am "b", split with tabs and having trailing spaces.', "Verifying that 'AN/test.conf's 'foo::bar::b' has whitespaces removed as expected."); |
||||
cmp_ok($an->data->{foo}{baz}{1}, 'eq', 'This is \'1\' with no spaces', "Verifying that 'AN/test.conf's 'foo::baz::1' parsed without spaces around '='."); |
||||
cmp_ok($an->data->{foo}{baz}{2}, 'eq', 'I had a $dollar = sign and split with tabs.', "Verifying that 'AN/test.conf's 'foo::baz::2' had no trouble with a '\$' and '=' characters in the string."); |
||||
# read_file was tested earlier. |
||||
# read_mode was tested earlier. |
||||
# search_directories |
||||
my $array1 = $an->Storage->search_directories; |
||||
my $a1_count = @{$array1}; |
||||
cmp_ok($a1_count, '>', 0, "Verifying that Storage->search_directories has at least one entry. Found: [$a1_count] directories."); |
||||
$an->Storage->search_directories({directories => "/root,/usr/bin,/some/fake/directory"}); |
||||
my $array2 = $an->Storage->search_directories; |
||||
my $a2_count = @{$array2}; |
||||
cmp_ok($a2_count, '==', 2, "Verifying that Storage->search_directories now has 2 entries from a passed in CSV, testing that the list changed and a fake directory was dropped."); |
||||
$an->Storage->search_directories({directories => ["/usr/bin", "/tmp", "/home"] }); |
||||
my $array3 = $an->Storage->search_directories; |
||||
my $a3_count = @{$array3}; |
||||
cmp_ok($a3_count, '==', 3, "Verifying that Storage->search_directories now has 3 entries from a passed in array reference, verifying that the list changed again."); |
||||
$an->Storage->search_directories({directories => "invalid" }); |
||||
my $array4 = $an->Storage->search_directories; |
||||
my $a4_count = @{$array4}; |
||||
cmp_ok($a4_count, '==', $a1_count, "Verifying that Storage->search_directories has the original number of directories: [$a4_count] after being called with an invalid 'directories' parameter, showing that it reset properly."); |
||||
# write_file was tested earlier |
||||
# Cleanup. |
||||
unlink $test_file; |
||||
unlink $copy_file; |
||||
foreach my $this_directory ("/tmp/an-tools/test/directory", "/tmp/an-tools/test", "/tmp/an-tools") |
||||
{ |
||||
rmdir $this_directory or die "Failed to remove the test directory: [$this_directory] (from a previous test?). The error was: $!\n"; |
||||
} |
||||
|
||||
### AN::Tools::System tests |
||||
# call was tested during the Log->entry test and will be tested further below. |
||||
# Daemon tests require that we create a test daemon and a unit for it... |
||||
my $test_daemon_file = "/tmp/an-tools-test.daemon"; |
||||
my $test_daemon_body = q|#!/usr/bin/perl |
||||
# This is a test daemon created for the AN::Tools test suite. It can safely be deleted. |
||||
|
||||
use strict; |
||||
use warnings; |
||||
use AN::Tools; |
||||
my $an = AN::Tools->new(); |
||||
$an->Log->entry({level => 1, priority => "info", raw => "AN::Tools Test daemon started."}); |
||||
|
||||
while(1) |
||||
{ |
||||
sleep 2; |
||||
$an->Log->entry({level => 1, priority => "info", raw => "AN::Tools Test daemon looped..."}); |
||||
} |
||||
|
||||
exit; |
||||
|; |
||||
$an->Storage->write_file({body => $test_daemon_body, file => $test_daemon_file, group => "root", user => "root", mode => "755", overwrite => 1}); |
||||
my $test_service_name = "an-tools-test.service"; |
||||
my $test_service_file = "/usr/lib/systemd/system/".$test_service_name; |
||||
my $test_service_body = "[Unit] |
||||
Description=Test daemon used by AN::Tools test suite. It can safely be ignored/deleted. |
||||
|
||||
[Service] |
||||
Type=simple |
||||
ExecStart=$test_daemon_file |
||||
ExecStop=/bin/kill -WINCH \${MAINPID} |
||||
"; |
||||
$an->Storage->write_file({body => $test_service_body, file => $test_service_file, group => "root", user => "root", mode => "644", overwrite => 1}); |
||||
$an->System->call({shell_call => $an->data->{path}{exe}{systemctl}." daemon-reload"}); |
||||
$an->System->stop_daemon({daemon => $test_service_name}); # Just in case... |
||||
# check_daemon |
||||
my $test_daemon_rc = $an->System->check_daemon({daemon => $test_service_name}); |
||||
is($test_daemon_rc, "0", "Verifying that 'System->check_daemon' was able to confirm that the test service: [".$test_service_name."] was stopped."); |
||||
$test_daemon_rc = ""; |
||||
$test_daemon_rc = $an->System->start_daemon({daemon => $test_service_name}); |
||||
is($test_daemon_rc, "0", "Verifying that 'System->start_daemon' was able to start the test service: [".$test_service_name."]."); |
||||
$test_daemon_rc = ""; |
||||
$test_daemon_rc = $an->System->check_daemon({daemon => $test_service_name}); |
||||
is($test_daemon_rc, "1", "Verifying that 'System->check_daemon' was able to confirm that the test service: [".$test_service_name."] is now running."); |
||||
$test_daemon_rc = ""; |
||||
$test_daemon_rc = $an->System->stop_daemon({daemon => $test_service_name}); |
||||
is($test_daemon_rc, "0", "Verifying that 'System->stop_daemon' was able to stop the test service: [".$test_service_name."]."); |
||||
$test_daemon_rc = ""; |
||||
$test_daemon_rc = $an->System->check_daemon({daemon => $test_service_name}); |
||||
is($test_daemon_rc, "0", "Verifying that 'System->check_daemon' was able to confirm that the test service: [".$test_service_name."] was stopped."); |
||||
|
||||
# Cleanup |
||||
unlink $test_service_file; |
||||
unlink $test_daemon_file; |
||||
$an->System->call({shell_call => $an->data->{path}{exe}{systemctl}." daemon-reload"}); |
||||
|
||||
### AN::Tools::Template tests |
||||
# We're going to need a fake template file to test. |
||||
my $test_template_file = "/tmp/an-tools.html"; |
||||
my $test_template_body = '<!-- start test1 --> |
||||
This is test template #1. |
||||
<!-- end test1 --> |
||||
|
||||
<!-- start test2 --> |
||||
This is test template #2. It has a replacement: [#!variable!test!#]. |
||||
<!-- end test2 --> |
||||
'; |
||||
$an->Storage->write_file({body => $test_template_body, file => $test_template_file, mode => "644", overwrite => 1}); |
||||
# get |
||||
my $test1_template = $an->Template->get({file => $test_template_file, name => "test1"}); |
||||
is($test1_template, "This is test template #1.\n", "Verifying that 'Template->get' was able to read a test template."); |
||||
my $test2_template = $an->Template->get({file => $test_template_file, name => "test2", variables => { test => "boo!" }}); |
||||
is($test2_template, "This is test template #2. It has a replacement: [boo!].\n", "Verifying that 'Template->get' was able to read a test template with a variable insertion."); |
||||
is($an->Template->skin, "alteeve", "Verifying that 'Template->skin' is initially set to 'alteeve'."); |
||||
$an->Template->skin({fatal => 0, set => "test"}); # We disable fatal because there may be no skin directory yet. |
||||
is($an->Template->skin, "test", "Verifying that 'Template->skin' was changed to 'test'."); |
||||
$an->Template->skin({fatal => 0, set => "alteeve"}); |
||||
is($an->Template->skin, "alteeve", "Verifying that 'Template->skin' was changed back to 'alteeve'."); |
||||
# Clean up |
||||
unlink $test_template_file; |
||||
|
||||
### AN::Tools::Validate tests |
||||
# is_ipv4 |
||||
is($an->Validate->is_ipv4({ip => "0.0.0.0"}), "1", "Verifying that 'Validate->is_ipv4' recognizes '0.0.0.0' as a valid IP address."); |
||||
is($an->Validate->is_ipv4({ip => "255.255.255.255"}), "1", "Verifying that 'Validate->is_ipv4' recognizes '255.255.255.255' as a valid IP address."); |
||||
is($an->Validate->is_ipv4({ip => "256.255.255.255"}), "0", "Verifying that 'Validate->is_ipv4' recognizes '256.255.255.255' as an invalid IP address."); |
||||
is($an->Validate->is_ipv4({ip => "alteeve.com"}), "0", "Verifying that 'Validate->is_ipv4' recognizes 'alteeve.com' as an invalid IP address."); |
||||
is($an->Validate->is_ipv4({ip => "::1"}), "0", "Verifying that 'Validate->is_ipv4' recognizes '::1' as an invalid IP address."); |
||||
my $test_uuid = $an->Get->uuid; |
||||
is($an->Validate->is_uuid({uuid => $test_uuid}), "1", "Verifying that 'Validate->is_uuid' recognized: [".$test_uuid."] as a valid UUID."); |
||||
my $bad_uuid_1 = $test_uuid; |
||||
$bad_uuid_1 =~ s/-//g; |
||||
is($an->Validate->is_uuid({uuid => $bad_uuid_1}), "0", "Verifying that 'Validate->is_uuid' recognized: [".$bad_uuid_1."] as an invalid UUID."); |
||||
my $bad_uuid_2 = uc($test_uuid); |
||||
is($an->Validate->is_uuid({uuid => $bad_uuid_2}), "0", "Verifying that 'Validate->is_uuid' recognized: [".$bad_uuid_2."] as an invalid UUID."); |
||||
my $bad_uuid_3 = $test_uuid."toolong"; |
||||
is($an->Validate->is_uuid({uuid => $bad_uuid_3}), "0", "Verifying that 'Validate->is_uuid' recognized: [".$bad_uuid_3."] as an invalid UUID."); |
||||
|
||||
### AN::Tools::Words tests |
||||
# clean_spaces |
||||
my $clean_string1 = " A line with spaces all over "; |
||||
my $clean_string2 = "A line with spaces at the end only "; |
||||
my $clean_string3 = " A line with spaces in the front only"; |
||||
my $clean_string4 = "A line with spaces in the middle only"; |
||||
is($an->Words->clean_spaces({string => $clean_string1}), "A line with spaces all over", "Verifying that 'Words->clean_spaces' cleaned up a string with random spaces."); |
||||
is($an->Words->clean_spaces({string => $clean_string2}), "A line with spaces at the end only", "Verifying that 'Words->clean_spaces' cleaned up a string spaces at the end of a string."); |
||||
is($an->Words->clean_spaces({string => $clean_string3}), "A line with spaces in the front only", "Verifying that 'Words->clean_spaces' cleaned up a string with spaces in the front only."); |
||||
is($an->Words->clean_spaces({string => $clean_string4}), "A line with spaces in the middle only", "Verifying that 'Words->clean_spaces' cleaned up a string with spaces in the middle only."); |
||||
# key |
||||
is($an->Words->key({key => "t_0001"}), "Test replace: [#!variable!test!#].", "Verifying that 'Words->key' returned the Canadian English 't_0001' string."); |
||||
is($an->Words->key({key => "t_0001", language => "jp"}), "テスト いれかえる: [#!variable!test!#]。", "Verifying that 'Words->read' returned the Japanese 't_0001' string."); |
||||
is($an->Words->key({key => "bad_key"}), "#!not_found!#", "Verified that 'Words->key' returns '#!not_found!#' for a bad key."); |
||||
is($an->Words->key({key => "t_0003", language => "jp"}), "#!not_found!#", "Verifying that 'Words->read' returned '#!not_found!#' for the missing 't_0003' key."); |
||||
# language |
||||
is($an->Words->language, "en_CA", "Verifying the default words language is 'en_CA'."); |
||||
$an->Words->language({set => "jp"}); |
||||
is($an->Words->language, "jp", "Verifying the words language was changed to 'jp'."); |
||||
$an->Words->language({set => "en_CA"}); |
||||
is($an->Words->language, "en_CA", "Verifying the words language is back to 'en_CA'."); |
||||
# read |
||||
### NOTE: At this time, we don't test for unreadable files (rc = 3) or general read faults as set by XML::Simple (rc = 4). |
||||
is($an->Words->read({file => $an->data->{path}{words}{'an-tools.xml'}}), 0, "Verifying that 'Words->read' properly returned '0' when asked to read the AN::Tools's words file."); |
||||
is($an->Words->read({file => ''}), 1, "Verifying that 'Words->read' properly returned '1' when asked to read a works file without a file being passed."); |
||||
is($an->Words->read({file => '/tmp/dummy.xml'}), 2, "Verifying that 'Words->read' properly returned '2' when asked to read a non-existent file."); |
||||
# string |
||||
my $test_string1 = $an->Words->string({ |
||||
key => "t_0005", |
||||
variables => { |
||||
test => "result!", |
||||
first => "1st", |
||||
second => "2nd", |
||||
}, |
||||
}); |
||||
is($test_string1, " |
||||
This is a multi-line test string with various items to insert. |
||||
|
||||
It also has some #!invalid!# replacement #!keys!# to test the escaping and restoring. |
||||
|
||||
Here is the default output language: [en_CA] |
||||
Here we will inject 't_0000': [Test replace: [result!].] |
||||
Here we will inject 't_0002' with its embedded variables: [Test Out of order: [2nd] replace: [1st].] |
||||
Here we will inject 't_0006', which injects 't_0001' which has a variable: [This string embeds 't_0001': [Test replace: [result!].]]. |
||||
", "Verifying string processing in the default (Canadian English) language."); |
||||
my $test_string2 = $an->Words->string({ |
||||
language => "jp", |
||||
key => "t_0005", |
||||
variables => { |
||||
test => "result!", |
||||
first => "1st", |
||||
second => "2nd", |
||||
}, |
||||
}); |
||||
is($test_string2, " |
||||
これは、挿入するさまざまな項目を含む複数行のテスト文字列です。 |
||||
|
||||
#!無効#!な置換!#キー!#を使ってエスケープとリストアをテストすることもできます。 |
||||
|
||||
デフォルトの出力言語は次のとおりです:「en_CA」 |
||||
ここで、「t_0000」を挿入します:[テスト いれかえる: [result!]。] |
||||
ここでは、 「t_0002」に埋め込み変数を挿入します:「テスト、 整理: [2nd]/[1st]。」 |
||||
ここでは変数 「この文字列には「t_0001」が埋め込まれています:「テスト いれかえる: [result!]。」」を持つ 「t_0001」を注入する 「t_0006」を注入します。 |
||||
", "Verifying string processing in Japanese."); |
||||
|
||||
### DONE! |
||||
# Tell the user that we're done making noise in their logs |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "log_0049"}); |
@ -0,0 +1,604 @@ |
||||
#!/usr/bin/perl |
||||
|
||||
use strict; |
||||
use warnings; |
||||
use POSIX; |
||||
use Data::Dumper; |
||||
use utf8; |
||||
|
||||
# Be nice and set a version number. |
||||
our $VERSION = "3.0.0"; |
||||
our $THIS_FILE = "Tools.t"; |
||||
|
||||
# Call in the test module, telling it how many tests to expect to run. |
||||
use Test::More tests => 200; |
||||
|
||||
# Load my module via 'use_ok' test. |
||||
BEGIN |
||||
{ |
||||
print "Beginning tests of the Anvil::Tools suite of modules.\n"; |
||||
use_ok('Anvil::Tools', 3.0.0); |
||||
} |
||||
|
||||
### Core tests |
||||
my $anvil = Anvil::Tools->new(); |
||||
like($anvil, qr/^Anvil::Tools=HASH\(0x\w+\)$/, "Verifying that Anvil::Tools object is valid."); |
||||
like($anvil->data, qr/^HASH\(0x\w+\)$/, "Verifying that 'data' is a hash reference."); |
||||
is($anvil->environment, "cli", "Verifying that environment initially reports 'cli'."); |
||||
$anvil->environment('html'); |
||||
is($anvil->environment, "html", "Verifying that environment was properly set to 'html'."); |
||||
$anvil->environment('cli'); |
||||
is($anvil->environment, "cli", "Verifying that environment was properly reset back to 'cli'."); |
||||
|
||||
# Test handles to child modules. |
||||
like($anvil->Alert, qr/^Anvil::Tools::Alert=HASH\(0x\w+\)$/, "Verifying that 'Alert' is a handle to Anvil::Tools::Alert."); |
||||
like($anvil->Convert, qr/^Anvil::Tools::Convert=HASH\(0x\w+\)$/, "Verifying that 'Convert' is a handle to Anvil::Tools::Convert."); |
||||
like($anvil->Database, qr/^Anvil::Tools::Database=HASH\(0x\w+\)$/, "Verifying that 'Database' is a handle to Anvil::Tools::Database."); |
||||
like($anvil->Get, qr/^Anvil::Tools::Get=HASH\(0x\w+\)$/, "Verifying that 'Get' is a handle to Anvil::Tools::Get."); |
||||
like($anvil->Log, qr/^Anvil::Tools::Log=HASH\(0x\w+\)$/, "Verifying that 'Log' is a handle to Anvil::Tools::Log."); |
||||
like($anvil->Storage, qr/^Anvil::Tools::Storage=HASH\(0x\w+\)$/, "Verifying that 'Storage' is a handle to Anvil::Tools::Storage."); |
||||
like($anvil->System, qr/^Anvil::Tools::System=HASH\(0x\w+\)$/, "Verifying that 'System' is a handle to Anvil::Tools::System."); |
||||
like($anvil->Template, qr/^Anvil::Tools::Template=HASH\(0x\w+\)$/, "Verifying that 'Template' is a handle to Anvil::Tools::Template."); |
||||
like($anvil->Validate, qr/^Anvil::Tools::Validate=HASH\(0x\w+\)$/, "Verifying that 'Validate' is a handle to Anvil::Tools::Validate."); |
||||
like($anvil->Words, qr/^Anvil::Tools::Words=HASH\(0x\w+\)$/, "Verifying that 'Words' is a handle to Anvil::Tools::Words."); |
||||
|
||||
### Special |
||||
# We log a note telling the user to ignore log entries caused by this test suite. We'll then read it back and |
||||
# make sure it logged properly |
||||
$anvil->Log->entry({level => 0, priority => "alert", key => "log_0048"}); |
||||
my $message = $anvil->Words->string({key => "log_0048"}); |
||||
my $last_log = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{journalctl}." -t anvil --lines 1 --full --output cat --no-pager"}); |
||||
is($last_log, $message, "Verified that we could write a log entry to journalctl by warning the user of incoming warnings and errors."); |
||||
|
||||
### Anvil::Tools::Alert tests |
||||
# <none yet> |
||||
|
||||
### Anvil::Tools::Convert tests |
||||
# cidr tests |
||||
is($anvil->Convert->cidr({cidr => "fake"}), "", "Verifying that Convert->cidr properly returned an empty string for a bad 'cidr' parameter."); |
||||
is($anvil->Convert->cidr({cidr => "0"}), "0.0.0.0", "Verifying that Convert->cidr properly returned '0.0.0.0' when given a 'cidr' parameter of '0'."); |
||||
is($anvil->Convert->cidr({cidr => "1"}), "128.0.0.0", "Verifying that Convert->cidr properly returned '128.0.0.0' when given a 'cidr' parameter of '1'."); |
||||
is($anvil->Convert->cidr({cidr => "2"}), "192.0.0.0", "Verifying that Convert->cidr properly returned '192.0.0.0' when given a 'cidr' parameter of '2'."); |
||||
is($anvil->Convert->cidr({cidr => "3"}), "224.0.0.0", "Verifying that Convert->cidr properly returned '224.0.0.0' when given a 'cidr' parameter of '3'."); |
||||
is($anvil->Convert->cidr({cidr => "4"}), "240.0.0.0", "Verifying that Convert->cidr properly returned '240.0.0.0' when given a 'cidr' parameter of '4'."); |
||||
is($anvil->Convert->cidr({cidr => "5"}), "248.0.0.0", "Verifying that Convert->cidr properly returned '248.0.0.0' when given a 'cidr' parameter of '5'."); |
||||
is($anvil->Convert->cidr({cidr => "6"}), "252.0.0.0", "Verifying that Convert->cidr properly returned '252.0.0.0' when given a 'cidr' parameter of '6'."); |
||||
is($anvil->Convert->cidr({cidr => "7"}), "254.0.0.0", "Verifying that Convert->cidr properly returned '254.0.0.0' when given a 'cidr' parameter of '7'."); |
||||
is($anvil->Convert->cidr({cidr => "8"}), "255.0.0.0", "Verifying that Convert->cidr properly returned '255.0.0.0' when given a 'cidr' parameter of '8'."); |
||||
is($anvil->Convert->cidr({cidr => "9"}), "255.128.0.0", "Verifying that Convert->cidr properly returned '255.128.0.0' when given a 'cidr' parameter of '9'."); |
||||
is($anvil->Convert->cidr({cidr => "10"}), "255.192.0.0", "Verifying that Convert->cidr properly returned '255.192.0.0' when given a 'cidr' parameter of '10'."); |
||||
is($anvil->Convert->cidr({cidr => "11"}), "255.224.0.0", "Verifying that Convert->cidr properly returned '255.224.0.0' when given a 'cidr' parameter of '11'."); |
||||
is($anvil->Convert->cidr({cidr => "12"}), "255.240.0.0", "Verifying that Convert->cidr properly returned '255.240.0.0' when given a 'cidr' parameter of '12'."); |
||||
is($anvil->Convert->cidr({cidr => "13"}), "255.248.0.0", "Verifying that Convert->cidr properly returned '255.248.0.0' when given a 'cidr' parameter of '13'."); |
||||
is($anvil->Convert->cidr({cidr => "14"}), "255.252.0.0", "Verifying that Convert->cidr properly returned '255.252.0.0' when given a 'cidr' parameter of '14'."); |
||||
is($anvil->Convert->cidr({cidr => "15"}), "255.254.0.0", "Verifying that Convert->cidr properly returned '255.254.0.0' when given a 'cidr' parameter of '15'."); |
||||
is($anvil->Convert->cidr({cidr => "16"}), "255.255.0.0", "Verifying that Convert->cidr properly returned '255.255.0.0' when given a 'cidr' parameter of '16'."); |
||||
is($anvil->Convert->cidr({cidr => "17"}), "255.255.128.0", "Verifying that Convert->cidr properly returned '255.255.128.0' when given a 'cidr' parameter of '17'."); |
||||
is($anvil->Convert->cidr({cidr => "18"}), "255.255.192.0", "Verifying that Convert->cidr properly returned '255.255.192.0' when given a 'cidr' parameter of '18'."); |
||||
is($anvil->Convert->cidr({cidr => "19"}), "255.255.224.0", "Verifying that Convert->cidr properly returned '255.255.224.0' when given a 'cidr' parameter of '19'."); |
||||
is($anvil->Convert->cidr({cidr => "20"}), "255.255.240.0", "Verifying that Convert->cidr properly returned '255.255.240.0' when given a 'cidr' parameter of '20'."); |
||||
is($anvil->Convert->cidr({cidr => "21"}), "255.255.248.0", "Verifying that Convert->cidr properly returned '255.255.248.0' when given a 'cidr' parameter of '21'."); |
||||
is($anvil->Convert->cidr({cidr => "22"}), "255.255.252.0", "Verifying that Convert->cidr properly returned '255.255.252.0' when given a 'cidr' parameter of '22'."); |
||||
is($anvil->Convert->cidr({cidr => "23"}), "255.255.254.0", "Verifying that Convert->cidr properly returned '255.255.254.0' when given a 'cidr' parameter of '23'."); |
||||
is($anvil->Convert->cidr({cidr => "24"}), "255.255.255.0", "Verifying that Convert->cidr properly returned '255.255.255.0' when given a 'cidr' parameter of '24'."); |
||||
is($anvil->Convert->cidr({cidr => "25"}), "255.255.255.128", "Verifying that Convert->cidr properly returned '255.255.255.128' when given a 'cidr' parameter of '25'."); |
||||
is($anvil->Convert->cidr({cidr => "26"}), "255.255.255.192", "Verifying that Convert->cidr properly returned '255.255.255.192' when given a 'cidr' parameter of '26'."); |
||||
is($anvil->Convert->cidr({cidr => "27"}), "255.255.255.224", "Verifying that Convert->cidr properly returned '255.255.255.224' when given a 'cidr' parameter of '27'."); |
||||
is($anvil->Convert->cidr({cidr => "28"}), "255.255.255.240", "Verifying that Convert->cidr properly returned '255.255.255.240' when given a 'cidr' parameter of '28'."); |
||||
is($anvil->Convert->cidr({cidr => "29"}), "255.255.255.248", "Verifying that Convert->cidr properly returned '255.255.255.248' when given a 'cidr' parameter of '29'."); |
||||
is($anvil->Convert->cidr({cidr => "30"}), "255.255.255.252", "Verifying that Convert->cidr properly returned '255.255.255.252' when given a 'cidr' parameter of '30'."); |
||||
is($anvil->Convert->cidr({cidr => "31"}), "255.255.255.254", "Verifying that Convert->cidr properly returned '255.255.255.254' when given a 'cidr' parameter of '31'."); |
||||
is($anvil->Convert->cidr({cidr => "32"}), "255.255.255.255", "Verifying that Convert->cidr properly returned '255.255.255.255' when given a 'cidr' parameter of '32'."); |
||||
is($anvil->Convert->cidr({subnet => "fake"}), "", "Verifying that Convert->cidr properly returned an empty string for a bad 'subnet' parameter."); |
||||
is($anvil->Convert->cidr({subnet => "0.0.0.0"}), "0", "Verifying that Convert->cidr properly returned '0' when given a 'subnet' parameter of '0.0.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "128.0.0.0"}), "1", "Verifying that Convert->cidr properly returned '1' when given a 'subnet' parameter of '128.0.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "192.0.0.0"}), "2", "Verifying that Convert->cidr properly returned '2' when given a 'subnet' parameter of '192.0.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "224.0.0.0"}), "3", "Verifying that Convert->cidr properly returned '3' when given a 'subnet' parameter of '224.0.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "240.0.0.0"}), "4", "Verifying that Convert->cidr properly returned '4' when given a 'subnet' parameter of '240.0.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "248.0.0.0"}), "5", "Verifying that Convert->cidr properly returned '5' when given a 'subnet' parameter of '248.0.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "252.0.0.0"}), "6", "Verifying that Convert->cidr properly returned '6' when given a 'subnet' parameter of '252.0.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "254.0.0.0"}), "7", "Verifying that Convert->cidr properly returned '7' when given a 'subnet' parameter of '254.0.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.0.0.0"}), "8", "Verifying that Convert->cidr properly returned '8' when given a 'subnet' parameter of '255.0.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.128.0.0"}), "9", "Verifying that Convert->cidr properly returned '9' when given a 'subnet' parameter of '255.128.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.192.0.0"}), "10", "Verifying that Convert->cidr properly returned '10' when given a 'subnet' parameter of '255.192.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.224.0.0"}), "11", "Verifying that Convert->cidr properly returned '11' when given a 'subnet' parameter of '255.224.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.240.0.0"}), "12", "Verifying that Convert->cidr properly returned '12' when given a 'subnet' parameter of '255.240.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.248.0.0"}), "13", "Verifying that Convert->cidr properly returned '13' when given a 'subnet' parameter of '255.248.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.252.0.0"}), "14", "Verifying that Convert->cidr properly returned '14' when given a 'subnet' parameter of '255.252.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.254.0.0"}), "15", "Verifying that Convert->cidr properly returned '15' when given a 'subnet' parameter of '255.254.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.0.0"}), "16", "Verifying that Convert->cidr properly returned '16' when given a 'subnet' parameter of '255.255.0.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.128.0"}), "17", "Verifying that Convert->cidr properly returned '17' when given a 'subnet' parameter of '255.255.128.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.192.0"}), "18", "Verifying that Convert->cidr properly returned '18' when given a 'subnet' parameter of '255.255.192.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.224.0"}), "19", "Verifying that Convert->cidr properly returned '19' when given a 'subnet' parameter of '255.255.224.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.240.0"}), "20", "Verifying that Convert->cidr properly returned '20' when given a 'subnet' parameter of '255.255.240.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.248.0"}), "21", "Verifying that Convert->cidr properly returned '21' when given a 'subnet' parameter of '255.255.248.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.252.0"}), "22", "Verifying that Convert->cidr properly returned '22' when given a 'subnet' parameter of '255.255.252.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.254.0"}), "23", "Verifying that Convert->cidr properly returned '23' when given a 'subnet' parameter of '255.255.254.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.255.0"}), "24", "Verifying that Convert->cidr properly returned '24' when given a 'subnet' parameter of '255.255.255.0'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.255.128"}), "25", "Verifying that Convert->cidr properly returned '25' when given a 'subnet' parameter of '255.255.255.128'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.255.192"}), "26", "Verifying that Convert->cidr properly returned '26' when given a 'subnet' parameter of '255.255.255.192'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.255.224"}), "27", "Verifying that Convert->cidr properly returned '27' when given a 'subnet' parameter of '255.255.255.224'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.255.240"}), "28", "Verifying that Convert->cidr properly returned '28' when given a 'subnet' parameter of '255.255.255.240'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.255.248"}), "29", "Verifying that Convert->cidr properly returned '29' when given a 'subnet' parameter of '255.255.255.248'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.255.252"}), "30", "Verifying that Convert->cidr properly returned '30' when given a 'subnet' parameter of '255.255.255.252'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.255.254"}), "31", "Verifying that Convert->cidr properly returned '31' when given a 'subnet' parameter of '255.255.255.254'."); |
||||
is($anvil->Convert->cidr({subnet => "255.255.255.255"}), "32", "Verifying that Convert->cidr properly returned '32' when given a 'subnet' parameter of '255.255.255.255'."); |
||||
|
||||
### Anvil::Tools::Database tests |
||||
# <none yet> |
||||
|
||||
### Anvil::Tools::Get tests |
||||
# date_and_time |
||||
like($anvil->Get->date_and_time(), qr/^\d\d\d\d\/\d\d\/\d\d \d\d:\d\d:\d\d$/, "Verifying the current date and time is returned."); |
||||
like($anvil->Get->date_and_time({date_only => 1}), qr/^\d\d\d\d\/\d\d\/\d\d$/, "Verifying the current date alone is returned."); |
||||
like($anvil->Get->date_and_time({time_only => 1}), qr/^\d\d:\d\d:\d\d$/, "Verifying the current time alone is returned."); |
||||
like($anvil->Get->date_and_time({file_name => 1}), qr/^\d\d\d\d-\d\d-\d\d_\d\d-\d\d-\d\d$/, "Verifying the current date and time is returned in a file-friendly format."); |
||||
like($anvil->Get->date_and_time({file_name => 1, date_only => 1}), qr/^\d\d\d\d-\d\d-\d\d$/, "Verifying the current date only is returned in a file-friendly format."); |
||||
like($anvil->Get->date_and_time({file_name => 1, time_only => 1}), qr/^\d\d-\d\d-\d\d$/, "Verifying the current time only is returned in a file-friendly format."); |
||||
# We can't be too specific because the user's TZ will shift the results |
||||
like($anvil->Get->date_and_time({use_time => 1234567890}), qr/2009\/02\/1[34] \d\d:\d\d:\d\d$/, "Verified that a specific unixtime returned the expected date."); |
||||
like($anvil->Get->date_and_time({use_time => 1234567890, offset => 31536000}), qr/2010\/02\/1[34] \d\d:\d\d:\d\d$/, "Verified that a specific unixtime with a one year in the future offset returned the expected date."); |
||||
like($anvil->Get->date_and_time({use_time => 1234567890, offset => -31536000}), qr/2008\/02\/1[34] \d\d:\d\d:\d\d$/, "Verified that a specific unixtime with a one year in the past offset returned the expected date."); |
||||
# host_uuid |
||||
like($anvil->Get->host_uuid, qr/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/, "Verifying ability to read host uuid."); |
||||
### TODO: How to test Get->switches? |
||||
# uuid |
||||
like($anvil->Get->uuid, qr/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/, "Verifying ability to generate a random uuid."); |
||||
|
||||
### Anvil::Tools::Log tests |
||||
# entry is tested at the start of this test suite. |
||||
# language |
||||
is($anvil->Log->language, "en_CA", "Verifying the default log language is 'en_CA'."); |
||||
$anvil->Log->language({set => "jp"}); |
||||
is($anvil->Log->language, "jp", "Verifying the log language was changed to 'jp'."); |
||||
$anvil->Log->language({set => "en_CA"}); |
||||
is($anvil->Log->language, "en_CA", "Verifying the log language is back to 'en_CA'."); |
||||
|
||||
# log_level |
||||
is($anvil->Log->level, "1", "Verifying the default log level is '1'."); |
||||
$anvil->Log->level({set => 0}); |
||||
is($anvil->Log->level, "0", "Verifying the log level changed to '0'."); |
||||
$anvil->Log->level({set => 1}); |
||||
is($anvil->Log->level, "1", "Verifying the log level changed to '1'."); |
||||
$anvil->Log->level({set => 2}); |
||||
is($anvil->Log->level, "2", "Verifying the log level changed to '2'."); |
||||
$anvil->Log->level({set => 3}); |
||||
is($anvil->Log->level, "3", "Verifying the log level changed to '3'."); |
||||
$anvil->Log->level({set => 4}); |
||||
is($anvil->Log->level, "4", "Verifying the log level changed to '4'."); |
||||
$anvil->Log->level({set => "foo"}); |
||||
is($anvil->Log->level, "4", "Verifying the log level stayed at '4' with bad input."); |
||||
$anvil->Log->level({set => 1}); |
||||
is($anvil->Log->level, "1", "Verifying the log level changed back to '1'."); |
||||
# secure |
||||
is($anvil->Log->secure, "0", "Verifying that logging secure messages is disabled by default."); |
||||
$anvil->Log->secure({set => "foo"}); |
||||
is($anvil->Log->secure, "0", "Verifying that logging secure messages stayed disabled on bad input."); |
||||
$anvil->Log->secure({set => 1}); |
||||
is($anvil->Log->secure, "1", "Verifying that logging secure messages was enabled."); |
||||
$anvil->Log->secure({set => 0}); |
||||
is($anvil->Log->secure, "0", "Verifying that logging secure messages was disabled again."); |
||||
# variables |
||||
$anvil->Log->variables({level => 0, list => { a => "1" }}); |
||||
my $list_a = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{journalctl}." -t anvil --lines 1 --full --output cat --no-pager"}); |
||||
is($list_a, "a: [1]", "Verified that we could log a list of variables (1 entry)."); |
||||
$anvil->Log->variables({level => 0, list => { a => "1", b => "2" }}); |
||||
my $list_b = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{journalctl}." -t anvil --lines 1 --full --output cat --no-pager"}); |
||||
is($list_b, "a: [1], b: [2]", "Verified that we could log a list of variables (2 entries)."); |
||||
$anvil->Log->variables({level => 0, list => { a => "1", b => "2", c => "3" }}); |
||||
my $list_c = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{journalctl}." -t anvil --lines 1 --full --output cat --no-pager"}); |
||||
is($list_c, "a: [1], b: [2], c: [3]", "Verified that we could log a list of variables (3 entries)."); |
||||
$anvil->Log->variables({level => 0, list => { a => "1", b => "2", c => "3", d => "4" }}); |
||||
my $list_d = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{journalctl}." -t anvil --lines 1 --full --output cat --no-pager"}); |
||||
is($list_d, "a: [1], b: [2], c: [3], d: [4]", "Verified that we could log a list of variables (4 entries)."); |
||||
$anvil->Log->variables({level => 0, list => { a => "1", b => "2", c => "3", d => "4", e => "5" }}); |
||||
my $list_e = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{journalctl}." -t anvil --lines 1 --full --output cat --no-pager"}); |
||||
my $say_variables = $anvil->Words->key({key => "log_0019"}); |
||||
my $expect_e = "$say_variables |
||||
|- a: [1] |
||||
|- b: [2] |
||||
|- c: [3] |
||||
|- d: [4] |
||||
\\- e: [5]"; |
||||
is($list_e, $expect_e, "Verified that we could log a list of variables (5 entries, line wrapping)."); |
||||
# _adjust_log_level - We're simulating switches to test Log->_adjust_log_level |
||||
$anvil->data->{switches}{V} = "#!set!#"; |
||||
$anvil->data->{switches}{v} = ""; |
||||
$anvil->data->{switches}{vv} = ""; |
||||
$anvil->data->{switches}{vvv} = ""; |
||||
$anvil->data->{switches}{vvvv} = ""; |
||||
$anvil->Log->_adjust_log_level; |
||||
is($anvil->Log->level, "0", "Verifying the log level was set to '0' with Log->_adjust_log_leve() with 'V' switch set."); |
||||
$anvil->data->{switches}{V} = ""; |
||||
$anvil->data->{switches}{v} = "#!set!#"; |
||||
$anvil->Log->_adjust_log_level; |
||||
is($anvil->Log->level, "1", "Verifying the log level was set to '1' with Log->_adjust_log_leve() with 'v' switch set."); |
||||
$anvil->data->{switches}{v} = ""; |
||||
$anvil->data->{switches}{vv} = "#!set!#"; |
||||
$anvil->Log->_adjust_log_level; |
||||
is($anvil->Log->level, "2", "Verifying the log level was set to '2' with Log->_adjust_log_leve() with 'vv' switch set."); |
||||
$anvil->data->{switches}{vv} = ""; |
||||
$anvil->data->{switches}{vvv} = "#!set!#"; |
||||
$anvil->Log->_adjust_log_level; |
||||
is($anvil->Log->level, "3", "Verifying the log level was set to '3' with Log->_adjust_log_leve() with 'vvv' switch set."); |
||||
$anvil->data->{switches}{vvv} = ""; |
||||
$anvil->data->{switches}{vvvv} = "#!set!#"; |
||||
$anvil->Log->_adjust_log_level; |
||||
is($anvil->Log->level, "4", "Verifying the log level was set to '4' with Log->_adjust_log_leve() with 'vvvv' switch set."); |
||||
$anvil->data->{switches}{vvvv} = ""; |
||||
$anvil->data->{switches}{v} = "#!set!#"; |
||||
$anvil->Log->_adjust_log_level; |
||||
is($anvil->Log->level, "1", "Verifying the log level was set back to '1' with Log->_adjust_log_leve() with 'v' switch set."); |
||||
|
||||
### Anvil::Tools::Storage tests - These happen a little out of order. |
||||
# We need to pick a user name and group name to use for these tests. So we'll start by reading in passwd. |
||||
my $passwd = $anvil->Storage->read_file({file => "/etc/passwd"}); |
||||
my $group = $anvil->Storage->read_file({file => "/etc/group"}); |
||||
my $read_ok = 0; |
||||
my $use_user = ""; |
||||
my $use_group = ""; |
||||
foreach my $line (split/\n/, $passwd) |
||||
{ |
||||
if ($line =~ /^root:/) |
||||
{ |
||||
$read_ok = 1; |
||||
} |
||||
elsif ($line =~ /^(\w+):x:\d/) |
||||
{ |
||||
$use_user = $1; |
||||
last; |
||||
} |
||||
} |
||||
foreach my $line (split/\n/, $group) |
||||
{ |
||||
if ($line =~ /^root:/) |
||||
{ |
||||
# skip |
||||
} |
||||
elsif ($line =~ /^(\w+):x:\d/) |
||||
{ |
||||
$use_group = $1; |
||||
last; |
||||
} |
||||
} |
||||
# print "[ Debug ] - Using the user: [$use_user] and the group: [$use_group] for testing.\n"; |
||||
is($read_ok, "1", "Verified that 'Storage->read_file' could read a file."); |
||||
# Write a file /tmp/foo |
||||
my $body = "This is a test file created as part of the Anvil::Tools test suite.\nYou can safely delete it if you wish.\n"; |
||||
my $test_file = "/tmp/anvil.test"; |
||||
if (-e $test_file) |
||||
{ |
||||
# remove the old test file. |
||||
unlink $test_file or die "The test file: [$test_file] exists (from a previous run?) and can't be removed. The error was: $!\n"; |
||||
} |
||||
$anvil->Storage->write_file({body => $body, file => $test_file, group => $use_group, user => $use_user, mode => "0666"}); |
||||
my $write_ok = 0; |
||||
if (-e $test_file) |
||||
{ |
||||
$write_ok = 1; |
||||
} |
||||
is($write_ok, "1", "Verifying that 'Storage->write_file' could write a file (tested writing to: [$test_file])."); |
||||
my $mode = $anvil->Storage->read_mode({target => $test_file}); |
||||
my ($uid, $gid) = (stat($test_file))[4,5]; |
||||
my $file_user_name = getpwuid($uid); |
||||
my $file_group_name = getgrgid($gid); |
||||
#print "[ Debug ] - test_file: [$test_file], mode: [$mode], owning user: [$file_user_name ($uid)], owning group: [$file_group_name ($gid)]\n"; |
||||
is($mode, "0666", "Verifying that 'Storage->write_file' set the mode correctly when writing a file."); |
||||
is($file_user_name, $use_user, "Verifying that 'Storage->write_file' set the user name properly when the file was written."); |
||||
is($file_group_name, $use_group, "Verifying that 'Storage->write_file' set the group name properly when the file was written."); |
||||
# change_mode |
||||
$anvil->Storage->change_mode({target => $test_file, mode => "4755"}); |
||||
$mode = $anvil->Storage->read_mode({target => $test_file}); |
||||
is($mode, "4755", "Verifying that 'Storage->change_mode' was able to change the mode of the test file (including setting the setuid and setgid sticky bits)."); |
||||
$anvil->Storage->change_mode({target => $test_file, mode => "644"}); |
||||
$mode = $anvil->Storage->read_mode({target => $test_file}); |
||||
is($mode, "0644", "Verifying that 'Storage->change_mode' was able to change the mode of the test file using three digits instead of four."); |
||||
# change_owner |
||||
$anvil->Storage->change_owner({target => $test_file, user => 0}); |
||||
$file_user_name = ""; |
||||
$file_group_name = ""; |
||||
($uid, $gid) = (stat($test_file))[4,5]; |
||||
$file_user_name = getpwuid($uid); |
||||
$file_group_name = getgrgid($gid); |
||||
is($file_user_name, "root", "Verifying that 'Storage->change_user', when passed only a user ID, changed the user."); |
||||
is($file_group_name, $use_group, "Verifying that 'Storage->change_user', when passed only a user ID, did not change the group."); |
||||
$anvil->Storage->change_owner({target => $test_file, user => $use_user}); |
||||
$file_user_name = ""; |
||||
$file_group_name = ""; |
||||
($uid, $gid) = (stat($test_file))[4,5]; |
||||
$file_user_name = getpwuid($uid); |
||||
$file_group_name = getgrgid($gid); |
||||
is($file_user_name, $use_user, "Verifying that 'Storage->change_user', when passed only a user name, changed the user."); |
||||
is($file_group_name, $use_group, "Verifying that 'Storage->change_user', when passed only a user ID, did not change the group."); |
||||
$anvil->Storage->change_owner({target => $test_file, group => 0}); |
||||
$file_user_name = ""; |
||||
$file_group_name = ""; |
||||
($uid, $gid) = (stat($test_file))[4,5]; |
||||
$file_user_name = getpwuid($uid); |
||||
$file_group_name = getgrgid($gid); |
||||
is($file_user_name, $use_user, "Verifying that 'Storage->change_user', when passed only a group ID, did not change the user."); |
||||
is($file_group_name, "root", "Verifying that 'Storage->change_user', when passed only a group ID, changed the group."); |
||||
$anvil->Storage->change_owner({target => $test_file, group => $use_group}); |
||||
$file_user_name = ""; |
||||
$file_group_name = ""; |
||||
($uid, $gid) = (stat($test_file))[4,5]; |
||||
$file_user_name = getpwuid($uid); |
||||
$file_group_name = getgrgid($gid); |
||||
is($file_user_name, $use_user, "Verifying that 'Storage->change_user', when passed only a group name, did not change the user."); |
||||
is($file_group_name, $use_group, "Verifying that 'Storage->change_user', when passed only a group name, changed the group."); |
||||
$anvil->Storage->change_owner({target => $test_file, user => "root", group => "root"}); |
||||
$file_user_name = ""; |
||||
$file_group_name = ""; |
||||
($uid, $gid) = (stat($test_file))[4,5]; |
||||
$file_user_name = getpwuid($uid); |
||||
$file_group_name = getgrgid($gid); |
||||
is($file_user_name, "root", "Verifying that 'Storage->change_user', when passed both a user and group name, changed the user."); |
||||
is($file_group_name, "root", "Verifying that 'Storage->change_user', when passed both a user and group name, changed the group."); |
||||
my $change_owner_rc = $anvil->Storage->change_owner({target => "", user => "root", group => "root"}); |
||||
is($change_owner_rc, "1", "Verifying that 'Storage->change_user', when passed no target, returned '1'."); |
||||
$change_owner_rc = ""; |
||||
$change_owner_rc = $anvil->Storage->change_owner({target => "/fake/file", user => "root", group => "root"}); |
||||
is($change_owner_rc, "1", "Verifying that 'Storage->change_user', when passed a bad file, returned '1'."); |
||||
# copy_file |
||||
my $copy_file = "/tmp/anvil.copy"; |
||||
my $copied_ok = 0; |
||||
if (-e $copy_file) |
||||
{ |
||||
unlink $copy_file or die "The test copy file: [$copy_file] exists (from a previous run?) and can't be removed. The error was: $!\n"; |
||||
} |
||||
$anvil->Storage->copy_file({source => $test_file, target => $copy_file}); |
||||
if (-e $copy_file) |
||||
{ |
||||
$copied_ok = 1; |
||||
} |
||||
is($copied_ok, "1", "Verifying that 'Storage->copy_file' was able to copy the test file."); |
||||
my $copy_rc = $anvil->Storage->copy_file({target => $copy_file}); |
||||
is($copy_rc, "1", "Verifying that 'Storage->copy_file' returned '1' when no source file was passed."); |
||||
$copy_rc = ""; |
||||
$copy_rc = $anvil->Storage->copy_file({source => $test_file}); |
||||
is($copy_rc, "2", "Verifying that 'Storage->copy_file' returned '2' when no target file was passed."); |
||||
$copy_rc = ""; |
||||
$copy_rc = $anvil->Storage->copy_file({source => $test_file, target => $copy_file}); |
||||
is($copy_rc, "3", "Verifying that 'Storage->copy_file' returned '3' when the target file already exists."); |
||||
$copy_rc = ""; |
||||
$copy_rc = $anvil->Storage->copy_file({source => $test_file, target => $copy_file, overwrite => 1}); |
||||
is($copy_rc, "0", "Verifying that 'Storage->copy_file' returned '0' when the target file already exists and overwrite was set."); |
||||
$copy_rc = ""; |
||||
$copy_rc = $anvil->Storage->copy_file({source => "/fake/file", target => $copy_file}); |
||||
is($copy_rc, "4", "Verifying that 'Storage->copy_file' returned '4' when the target file is passed but doesn't exist."); |
||||
# find |
||||
my $test_path = $anvil->Storage->find({ file => "Anvil/Tools.t" }); |
||||
is($test_path, "/usr/share/perl5/Anvil/Tools.t", "Verifying that Storage->find successfully found 'Anvil/Tools.t'."); |
||||
my $bad_path = $anvil->Storage->find({ file => "Anvil/wa.t" }); |
||||
is($bad_path, "#!not_found!#", "Verifying that Storage->find properly returned '#!not_found!#' for a non-existed file."); |
||||
# make_directory |
||||
my $test_directory = "/tmp/anvil/test/directory"; |
||||
if (-d $test_directory) |
||||
{ |
||||
foreach my $this_directory ("/tmp/anvil/test/directory", "/tmp/anvil/test", "/tmp/anvil") |
||||
{ |
||||
rmdir $this_directory or die "Failed to remove the test directory: [$this_directory] (from a previous test?). The error was: $!\n"; |
||||
} |
||||
} |
||||
# This uses an odd mode on purpose |
||||
$anvil->Storage->make_directory({directory => $test_directory, group => $use_group, user => $use_user, mode => "0757"}); |
||||
my $created_directory = 0; |
||||
if (-d $test_directory) |
||||
{ |
||||
$created_directory = 1; |
||||
} |
||||
is($created_directory, "1", "Verifying that 'Storage->create_directory' created a directory and its parents."); |
||||
my $directory_mode = $anvil->Storage->read_mode({target => $test_directory}); |
||||
($uid, $gid) = (stat($test_directory))[4,5]; |
||||
my $directory_user_name = getpwuid($uid); |
||||
my $directory_group_name = getgrgid($gid); |
||||
is($directory_mode, "0757", "Verifying that 'Storage->create_directory' created a directory with the requested mode."); |
||||
is($directory_user_name, $use_user, "Verifying that 'Storage->create_directory' created a directory with the requested owner."); |
||||
is($directory_group_name, $use_group, "Verifying that 'Storage->create_directory' created a directory with the requested group."); |
||||
# read_config |
||||
$anvil->data->{foo}{bar}{a} = "test"; |
||||
is($anvil->Storage->read_config({ file => "Anvil/test.conf" }), 0, "Verifying that 'Storage->read_config' successfully found 'Anvil/test.conf'."); |
||||
is($anvil->Storage->read_config({ file => "" }), 1, "Verifying that 'Storage->read_config' returns '1' when called without a 'file' parameter being set."); |
||||
is($anvil->Storage->read_config({ file => "Anvil/moo.conf" }), 2, "Verifying that 'Storage->read_config' returns '2' when the non-existent 'Anvil/moo.conf' is passed."); |
||||
cmp_ok($anvil->data->{foo}{bar}{a}, 'eq', 'I am "a"', "Verifying that 'Anvil/test.conf's 'foo::bar::a' overwrote an earlier set value."); |
||||
cmp_ok($anvil->data->{foo}{bar}{b}, 'eq', 'I am "b", split with tabs and having trailing spaces.', "Verifying that 'Anvil/test.conf's 'foo::bar::b' has whitespaces removed as expected."); |
||||
cmp_ok($anvil->data->{foo}{baz}{1}, 'eq', 'This is \'1\' with no spaces', "Verifying that 'Anvil/test.conf's 'foo::baz::1' parsed without spaces around '='."); |
||||
cmp_ok($anvil->data->{foo}{baz}{2}, 'eq', 'I had a $dollar = sign and split with tabs.', "Verifying that 'Anvil/test.conf's 'foo::baz::2' had no trouble with a '\$' and '=' characters in the string."); |
||||
# read_file was tested earlier. |
||||
# read_mode was tested earlier. |
||||
# search_directories |
||||
my $array1 = $anvil->Storage->search_directories; |
||||
my $a1_count = @{$array1}; |
||||
cmp_ok($a1_count, '>', 0, "Verifying that Storage->search_directories has at least one entry. Found: [$a1_count] directories."); |
||||
$anvil->Storage->search_directories({directories => "/root,/usr/bin,/some/fake/directory"}); |
||||
my $array2 = $anvil->Storage->search_directories; |
||||
my $a2_count = @{$array2}; |
||||
cmp_ok($a2_count, '==', 2, "Verifying that Storage->search_directories now has 2 entries from a passed in CSV, testing that the list changed and a fake directory was dropped."); |
||||
$anvil->Storage->search_directories({directories => ["/usr/bin", "/tmp", "/home"] }); |
||||
my $array3 = $anvil->Storage->search_directories; |
||||
my $a3_count = @{$array3}; |
||||
cmp_ok($a3_count, '==', 3, "Verifying that Storage->search_directories now has 3 entries from a passed in array reference, verifying that the list changed again."); |
||||
$anvil->Storage->search_directories({directories => "invalid" }); |
||||
my $array4 = $anvil->Storage->search_directories; |
||||
my $a4_count = @{$array4}; |
||||
cmp_ok($a4_count, '==', $a1_count, "Verifying that Storage->search_directories has the original number of directories: [$a4_count] after being called with an invalid 'directories' parameter, showing that it reset properly."); |
||||
# write_file was tested earlier |
||||
# Cleanup. |
||||
unlink $test_file; |
||||
unlink $copy_file; |
||||
foreach my $this_directory ("/tmp/anvil/test/directory", "/tmp/anvil/test", "/tmp/anvil") |
||||
{ |
||||
rmdir $this_directory or die "Failed to remove the test directory: [$this_directory] (from a previous test?). The error was: $!\n"; |
||||
} |
||||
|
||||
### Anvil::Tools::System tests |
||||
# call was tested during the Log->entry test and will be tested further below. |
||||
# Daemon tests require that we create a test daemon and a unit for it... |
||||
my $test_daemon_file = "/tmp/anvil-test.daemon"; |
||||
my $test_daemon_body = q|#!/usr/bin/perl |
||||
# This is a test daemon created for the Anvil::Tools test suite. It can safely be deleted. |
||||
|
||||
use strict; |
||||
use warnings; |
||||
use Anvil::Tools; |
||||
my $anvil->= Anvil::Tools->new(); |
||||
$anvil->Log->entry({level => 1, priority => "info", raw => "Anvil::Tools Test daemon started."}); |
||||
|
||||
while(1) |
||||
{ |
||||
sleep 2; |
||||
$anvil->Log->entry({level => 1, priority => "info", raw => "Anvil::Tools Test daemon looped..."}); |
||||
} |
||||
|
||||
exit; |
||||
|; |
||||
$anvil->Storage->write_file({body => $test_daemon_body, file => $test_daemon_file, group => "root", user => "root", mode => "755", overwrite => 1}); |
||||
my $test_service_name = "anvil-test.service"; |
||||
my $test_service_file = "/usr/lib/systemd/system/".$test_service_name; |
||||
my $test_service_body = "[Unit] |
||||
Description=Test daemon used by Anvil::Tools test suite. It can safely be ignored/deleted. |
||||
|
||||
[Service] |
||||
Type=simple |
||||
ExecStart=$test_daemon_file |
||||
ExecStop=/bin/kill -WINCH \${MAINPID} |
||||
"; |
||||
$anvil->Storage->write_file({body => $test_service_body, file => $test_service_file, group => "root", user => "root", mode => "644", overwrite => 1}); |
||||
$anvil->System->call({shell_call => $anvil->data->{path}{exe}{systemctl}." daemon-reload"}); |
||||
$anvil->System->stop_daemon({daemon => $test_service_name}); # Just in case... |
||||
# check_daemon |
||||
my $test_daemon_rc = $anvil->System->check_daemon({daemon => $test_service_name}); |
||||
is($test_daemon_rc, "0", "Verifying that 'System->check_daemon' was able to confirm that the test service: [".$test_service_name."] was stopped."); |
||||
$test_daemon_rc = ""; |
||||
$test_daemon_rc = $anvil->System->start_daemon({daemon => $test_service_name}); |
||||
is($test_daemon_rc, "0", "Verifying that 'System->start_daemon' was able to start the test service: [".$test_service_name."]."); |
||||
$test_daemon_rc = ""; |
||||
$test_daemon_rc = $anvil->System->check_daemon({daemon => $test_service_name}); |
||||
is($test_daemon_rc, "1", "Verifying that 'System->check_daemon' was able to confirm that the test service: [".$test_service_name."] is now running."); |
||||
$test_daemon_rc = ""; |
||||
$test_daemon_rc = $anvil->System->stop_daemon({daemon => $test_service_name}); |
||||
is($test_daemon_rc, "0", "Verifying that 'System->stop_daemon' was able to stop the test service: [".$test_service_name."]."); |
||||
$test_daemon_rc = ""; |
||||
$test_daemon_rc = $anvil->System->check_daemon({daemon => $test_service_name}); |
||||
is($test_daemon_rc, "0", "Verifying that 'System->check_daemon' was able to confirm that the test service: [".$test_service_name."] was stopped."); |
||||
|
||||
# Cleanup |
||||
unlink $test_service_file; |
||||
unlink $test_daemon_file; |
||||
$anvil->System->call({shell_call => $anvil->data->{path}{exe}{systemctl}." daemon-reload"}); |
||||
|
||||
### Anvil::Tools::Template tests |
||||
# We're going to need a fake template file to test. |
||||
my $test_template_file = "/tmp/anvil.html"; |
||||
my $test_template_body = '<!-- start test1 --> |
||||
This is test template #1. |
||||
<!-- end test1 --> |
||||
|
||||
<!-- start test2 --> |
||||
This is test template #2. It has a replacement: [#!variable!test!#]. |
||||
<!-- end test2 --> |
||||
'; |
||||
$anvil->Storage->write_file({body => $test_template_body, file => $test_template_file, mode => "644", overwrite => 1}); |
||||
# get |
||||
|
||||
my $test1_template = $anvil->Template->get({file => $test_template_file, name => "test1"}); |
||||
is($test1_template, "This is test template #1.\n", "Verifying that 'Template->get' was able to read a test template."); |
||||
my $test2_template = $anvil->Template->get({file => $test_template_file, name => "test1", show_name => 1}); |
||||
is($test2_template, "<!-- start: [/tmp/anvil.html] -> [test1] -->\nThis is test template #1.\n<!-- end: [/tmp/anvil.html] -> [test1] -->\n", "Verifying that 'Template->get' was able to read a test template with the source in HTML comments."); |
||||
my $test3_template = $anvil->Template->get({file => $test_template_file, name => "test2", variables => { test => "boo!" }}); |
||||
is($test3_template, "This is test template #2. It has a replacement: [boo!].\n", "Verifying that 'Template->get' was able to read a test template with a variable insertion."); |
||||
is($anvil->Template->skin, "alteeve", "Verifying that 'Template->skin' is initially set to 'alteeve'."); |
||||
$anvil->Template->skin({fatal => 0, set => "test"}); # We disable fatal because there may be no skin directory yet. |
||||
is($anvil->Template->skin, "test", "Verifying that 'Template->skin' was changed to 'test'."); |
||||
$anvil->Template->skin({fatal => 0, set => "alteeve"}); |
||||
is($anvil->Template->skin, "alteeve", "Verifying that 'Template->skin' was changed back to 'alteeve'."); |
||||
# Clean up |
||||
unlink $test_template_file; |
||||
|
||||
### Anvil::Tools::Validate tests |
||||
# is_ipv4 |
||||
is($anvil->Validate->is_ipv4({ip => "0.0.0.0"}), "1", "Verifying that 'Validate->is_ipv4' recognizes '0.0.0.0' as a valid IP address."); |
||||
is($anvil->Validate->is_ipv4({ip => "255.255.255.255"}), "1", "Verifying that 'Validate->is_ipv4' recognizes '255.255.255.255' as a valid IP address."); |
||||
is($anvil->Validate->is_ipv4({ip => "256.255.255.255"}), "0", "Verifying that 'Validate->is_ipv4' recognizes '256.255.255.255' as an invalid IP address."); |
||||
is($anvil->Validate->is_ipv4({ip => "alteeve.com"}), "0", "Verifying that 'Validate->is_ipv4' recognizes 'alteeve.com' as an invalid IP address."); |
||||
is($anvil->Validate->is_ipv4({ip => "::1"}), "0", "Verifying that 'Validate->is_ipv4' recognizes '::1' as an invalid IP address."); |
||||
my $test_uuid = $anvil->Get->uuid; |
||||
is($anvil->Validate->is_uuid({uuid => $test_uuid}), "1", "Verifying that 'Validate->is_uuid' recognized: [".$test_uuid."] as a valid UUID."); |
||||
my $bad_uuid_1 = $test_uuid; |
||||
$bad_uuid_1 =~ s/-//g; |
||||
is($anvil->Validate->is_uuid({uuid => $bad_uuid_1}), "0", "Verifying that 'Validate->is_uuid' recognized: [".$bad_uuid_1."] as an invalid UUID."); |
||||
my $bad_uuid_2 = uc($test_uuid); |
||||
is($anvil->Validate->is_uuid({uuid => $bad_uuid_2}), "0", "Verifying that 'Validate->is_uuid' recognized: [".$bad_uuid_2."] as an invalid UUID."); |
||||
my $bad_uuid_3 = $test_uuid."toolong"; |
||||
is($anvil->Validate->is_uuid({uuid => $bad_uuid_3}), "0", "Verifying that 'Validate->is_uuid' recognized: [".$bad_uuid_3."] as an invalid UUID."); |
||||
|
||||
### Anvil::Tools::Words tests |
||||
# clean_spaces |
||||
my $clean_string1 = " A line with spaces all over "; |
||||
my $clean_string2 = "A line with spaces at the end only "; |
||||
my $clean_string3 = " A line with spaces in the front only"; |
||||
my $clean_string4 = "A line with spaces in the middle only"; |
||||
is($anvil->Words->clean_spaces({string => $clean_string1}), "A line with spaces all over", "Verifying that 'Words->clean_spaces' cleaned up a string with random spaces."); |
||||
is($anvil->Words->clean_spaces({string => $clean_string2}), "A line with spaces at the end only", "Verifying that 'Words->clean_spaces' cleaned up a string spaces at the end of a string."); |
||||
is($anvil->Words->clean_spaces({string => $clean_string3}), "A line with spaces in the front only", "Verifying that 'Words->clean_spaces' cleaned up a string with spaces in the front only."); |
||||
is($anvil->Words->clean_spaces({string => $clean_string4}), "A line with spaces in the middle only", "Verifying that 'Words->clean_spaces' cleaned up a string with spaces in the middle only."); |
||||
# key |
||||
is($anvil->Words->key({key => "t_0001"}), "Test replace: [#!variable!test!#].", "Verifying that 'Words->key' returned the Canadian English 't_0001' string."); |
||||
is($anvil->Words->key({key => "t_0001", language => "jp"}), "テスト いれかえる: [#!variable!test!#]。", "Verifying that 'Words->read' returned the Japanese 't_0001' string."); |
||||
is($anvil->Words->key({key => "bad_key"}), "#!not_found!#", "Verified that 'Words->key' returns '#!not_found!#' for a bad key."); |
||||
is($anvil->Words->key({key => "t_0003", language => "jp"}), "#!not_found!#", "Verifying that 'Words->read' returned '#!not_found!#' for the missing 't_0003' key."); |
||||
# language |
||||
is($anvil->Words->language, "en_CA", "Verifying the default words language is 'en_CA'."); |
||||
$anvil->Words->language({set => "jp"}); |
||||
is($anvil->Words->language, "jp", "Verifying the words language was changed to 'jp'."); |
||||
$anvil->Words->language({set => "en_CA"}); |
||||
is($anvil->Words->language, "en_CA", "Verifying the words language is back to 'en_CA'."); |
||||
# read |
||||
### NOTE: At this time, we don't test for unreadable files (rc = 3) or general read faults as set by XML::Simple (rc = 4). |
||||
|
||||
is($anvil->Words->read({file => $anvil->data->{path}{words}{'words.xml'}}), 0, "Verifying that 'Words->read' properly returned '0' when asked to read the Anvil::Tools's words file."); |
||||
|
||||
is($anvil->Words->read({file => ''}), 1, "Verifying that 'Words->read' properly returned '1' when asked to read a works file without a file being passed."); |
||||
is($anvil->Words->read({file => '/tmp/dummy.xml'}), 2, "Verifying that 'Words->read' properly returned '2' when asked to read a non-existent file."); |
||||
# string |
||||
my $test_string1 = $anvil->Words->string({ |
||||
key => "t_0005", |
||||
variables => { |
||||
test => "result!", |
||||
first => "1st", |
||||
second => "2nd", |
||||
}, |
||||
}); |
||||
is($test_string1, " |
||||
This is a multi-line test string with various items to insert. |
||||
|
||||
It also has some #!invalid!# replacement #!keys!# to test the escaping and restoring. |
||||
|
||||
Here is the default output language: [en_CA] |
||||
Here we will inject 't_0000': [Test replace: [result!].] |
||||
Here we will inject 't_0002' with its embedded variables: [Test Out of order: [2nd] replace: [1st].] |
||||
Here we will inject 't_0006', which injects 't_0001' which has a variable: [This string embeds 't_0001': [Test replace: [result!].]]. |
||||
", "Verifying string processing in the default (Canadian English) language."); |
||||
my $test_string2 = $anvil->Words->string({ |
||||
language => "jp", |
||||
key => "t_0005", |
||||
variables => { |
||||
test => "result!", |
||||
first => "1st", |
||||
second => "2nd", |
||||
}, |
||||
}); |
||||
is($test_string2, " |
||||
これは、挿入するさまざまな項目を含む複数行のテスト文字列です。 |
||||
|
||||
#!無効#!な置換!#キー!#を使ってエスケープとリストアをテストすることもできます。 |
||||
|
||||
デフォルトの出力言語は次のとおりです:「en_CA」 |
||||
ここで、「t_0000」を挿入します:[テスト いれかえる: [result!]。] |
||||
ここでは、 「t_0002」に埋め込み変数を挿入します:「テスト、 整理: [2nd]/[1st]。」 |
||||
ここでは変数 「この文字列には「t_0001」が埋め込まれています:「テスト いれかえる: [result!]。」」を持つ 「t_0001」を注入する 「t_0006」を注入します。 |
||||
", "Verifying string processing in Japanese."); |
||||
|
||||
### DONE! |
||||
# Tell the user that we're done making noise in their logs |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "log_0049"}); |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,22 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<!-- |
||||
Company: Alteeve's Niche, Inc. |
||||
License: GPL v2+ |
||||
Author: Madison Kelly <mkelly@alteeve.ca> |
||||
|
||||
This is the AN::Tools master 'words' file. |
||||
--> |
||||
|
||||
<words> |
||||
<meta version="3.0.0" languages="en_CA,jp"/> |
||||
<!-- Canadian English --> |
||||
<language name="en_CA" long_name="Canadian English" description="Created by Madison Kelly (mkelly@alteeve.ca) for the AN::Tools suite of perl modules"> |
||||
|
||||
|
||||
</language> |
||||
<!-- 日本語 --> |
||||
<language name="jp" long_name="日本語" description=">Created by Madison Kelly (mkelly@alteeve.ca) for the AN::Tools suite of perl modules."> |
||||
|
||||
</language> |
||||
</words> |
@ -1,5 +1,5 @@ |
||||
### DO NOT EDIT THIS FILE! |
||||
# This is a test configuration file used by AN::Tools to validate AN::Tools::Storage->read_config()'. If you |
||||
# This is a test configuration file used by Anvil::Tools to validate Anvil::Tools::Storage->read_config()'. If you |
||||
# change any of the variable = value pairs below, you MUST also update 'AN/Tools.t'! |
||||
foo::bar::a = I am "a" |
||||
foo::bar::b = I am "b", split with tabs and having trailing spaces. |
@ -0,0 +1,116 @@ |
||||
# This is the main Striker (and ScanCore) configuration file. |
||||
# |
||||
|
||||
database::1::host = 192.168.122.201 |
||||
database::1::port = 5432 |
||||
database::1::name = scancore |
||||
database::1::user = admin |
||||
database::1::password = Initial1 |
||||
database::1::ping_before_connect = 1 |
||||
|
||||
database::2::host = 192.168.122.202 |
||||
database::2::port = 5432 |
||||
database::2::name = scancore |
||||
database::2::user = admin |
||||
database::2::password = Initial1 |
||||
database::2::ping_before_connect = 1 |
||||
|
||||
# This is the schema for the ScanCore database. |
||||
sys::database::schema = /etc/scancore/scancore.sql |
||||
|
||||
# This puts a limit on how many queries (writes, generally) to make in a single batch transaction. This is |
||||
# useful when doing very large transacions, like resync'ing a large table, by limiting how long a given |
||||
# transaction can take and how much memory is used. |
||||
#sys::database::maximum_batch_size = 25000 |
||||
|
||||
# By default, we try to determine the host type using the host name. The rules used for this can be seen in |
||||
# 'perldoc Anvil::Tools::System -> determine_host_type'. If you are using non-standard host names, or for some |
||||
# other reason want to statically assign the host type, you can do so with this variable. Note that this sets |
||||
# the host type of this host only. You will need to set this appropriately on other hosts. |
||||
# |
||||
# Normally, you should not need to set this. |
||||
#sys::host_type = node |
||||
# This configuration file provides a way to override Anvil::Tools' built-in defaults. |
||||
|
||||
# This controls the default language. The value is the ISO code of the country's language you want to use by |
||||
# default. Note that the logging language is set with 'defaults::log::language' below. |
||||
# NOTE: Be sure the language exists before changing it! |
||||
#defaults::languages::output = en_CA |
||||
|
||||
# This controls how many loops Anvil::Tools::Words is allow to make while processing a string. This acts as a |
||||
# mechanism to exit infinite loops, and generally should not need to be changed. |
||||
#defaults::limits::string_loops = 1000 |
||||
|
||||
### Logging options |
||||
# This controls whether all database transactions are recorded or not. Genreally this should be left off |
||||
# unless you are debugging the program. |
||||
# WARNING: This ignores 'secure', and will always be logged. Be careful about exposing sensitive data! |
||||
#defaults::log::db_transactions = 0 |
||||
|
||||
# This controls what log facility to use by default. |
||||
# NOTE: This will always be 'authpriv' when a log entry is marked as secure. |
||||
#defaults::log::facility = local0 |
||||
|
||||
# This controls what language logs are recorded in. Be sure that the language exists before changing it! |
||||
#defaults::log::language = en_CA |
||||
|
||||
# This controls the default log level. See 'perldoc Anvil::Tools::Logs' for details. |
||||
#defaults::log::level = 1 |
||||
|
||||
# This controls whether sensitive log entries are logged or not. Generally, this should be left disabled! |
||||
#defaults::log::secure = 0, |
||||
|
||||
# THis sets the default log server to send the log entries to. Leave it blank in most cases. |
||||
#defaults::log::server = |
||||
|
||||
# This sets the default log tag used when logging an entry. Most programs will likely override this. |
||||
#defaults::log::tag = anvil |
||||
|
||||
|
||||
### Templates |
||||
# This sets the default template used when rendering HTML pages. It must be the same as the directory name |
||||
# under /var/www/html/skins/ |
||||
#defaults::template::html = alteeve |
||||
|
||||
|
||||
### Database |
||||
|
||||
# To keep ScanCore's database growth in check, an auto-archive mechanism is |
||||
# used by some agents where, at the end of each scan, the number of records in |
||||
# the history schema for a given table are counted (restricted to the agent's |
||||
# host, when appropriate). |
||||
# |
||||
# When the number exceeds the trigger, the number of records that are archived |
||||
# is approximately (number of records above trigger + 'count'). This is not an |
||||
# exact number because a representative timestamp will be selected from the |
||||
# hostory schema at this count, and then any record equal to or older than the |
||||
# time stamp is removed. |
||||
# |
||||
# To protect against the potential of using too much disk space, archives are |
||||
# off by default. Under normal behaviour, old records are simple removed. To |
||||
# enable the archive function, set this to '1'. |
||||
#scancore::archive::save_to_disk = 1 |
||||
# |
||||
# When archiving to disk is enabled, to protect against large memory use or |
||||
# long archive times in the case where the number of records to archive are |
||||
# particularly large, the 'division' value is used to break up the archive job |
||||
# into "chunks". Generally speaking, the division should be greater than the |
||||
# count, and never be needed. However, if the archive process takes too long, |
||||
# or if the archive was triggered well above the trigger value, the division |
||||
# can help prevent using too much memory at once. If division is set to '0', |
||||
# archive jobs will never be divided. |
||||
# |
||||
# The archives are all stored in the specified |
||||
# directory using the name format '<agent>.<table>.<timestamp>.bz2' and the |
||||
# archives are synced between dashboards for safe keeping. Archive files are |
||||
# never removed automatically. |
||||
# |
||||
# To disable auto-archiving entirely, set 'trigger' to '0'. |
||||
# |
||||
# NOTE: If the archive directory doesn't exist, ScanCore will create it |
||||
# automatically the first time it is needed. |
||||
sys::database::archive::compress = 1 |
||||
sys::database::archive::count = 50000 |
||||
sys::database::archive::directory = /usr/local/anvil/archives/ |
||||
sys::database::archive::division = 60000 |
||||
sys::database::archive::trigger = 100000 |
File diff suppressed because it is too large
Load Diff
@ -1,100 +0,0 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<!-- |
||||
Company: Alteeve's Niche, Inc. |
||||
License: GPL v2+ |
||||
Author: Madison Kelly <mkelly@alteeve.ca> |
||||
|
||||
This is the AN::Tools master 'words' file. |
||||
--> |
||||
|
||||
<words> |
||||
<meta version="3.0.0" languages="en_CA,jp"/> |
||||
<!-- Canadian English --> |
||||
<language name="en_CA" long_name="Canadian English" description="Striker/ScanCore language file."> |
||||
|
||||
<key name="brand_0001">Alteeve</key> |
||||
<key name="brand_0002">Anvil!</key> |
||||
<key name="brand_0003">Striker</key> |
||||
<key name="brand_0004">ScanCore</key> |
||||
<key name="brand_0005"><![CDATA[© 2017 <a href="https://alteeve.com/" target="_new">Alteeve's Niche! Inc.</a>, Toronto, Ontario, Canada]]></key> |
||||
<key name="brand_0006"><![CDATA[<i>Anvil!</i>]]></key> |
||||
|
||||
<key name="header_0001">Current Network Interfaces and States</key> |
||||
<key name="header_0002">MAC Address</key> |
||||
<key name="header_0003">Name</key> |
||||
<key name="header_0004">State</key> |
||||
<key name="header_0005">Speed</key> |
||||
<key name="header_0006">Up Order</key> |
||||
|
||||
<!-- General strings shown in Striker --> |
||||
<key name="striker_0001">Welcome! Lets setup your #!string!brand_0003!# dashboard...</key> |
||||
<key name="striker_0002">We're going to ask you a few questions so that we can set things up for your environment. If you need help at any time, just click on the "[?]" icon in the top-right. Let's get started!</key> |
||||
<key name="striker_0003">Organization name</key> |
||||
<key name="striker_0004">This is the name of the company, organization or division that owns or maintains this #!string!brand_0006!#. This is a descriptive field and you can enter whatever makes most sense to you.</key> |
||||
<key name="striker_0005">Prefix</key> |
||||
<key name="striker_0006">This is a two to five character prefix used to identify this organization. It is used as the prefix for host names for dashboards, nodes and foundation pack equipment. You can use letters and numbers and set whatever makes sense to you.</key> |
||||
<key name="striker_0007">Domain Name</key> |
||||
<key name="striker_0008">This is the domain name you would like to use for this dashboard. This will also be used as the default domain used when creating new install manifests.</key> |
||||
<key name="striker_0009">Sequence Number</key> |
||||
<key name="striker_0010">If this is your first Striker, set this to '1'. If it is the second one, set '2'. If it is the third, '3' and so on.</key> |
||||
<key name="striker_0011">Internet-Facing Network Count</key> |
||||
<key name="striker_0012"><![CDATA[How many internal networks will this dashboard have access to? In most cases, this is just '1'.<br /><b>NOTE</b>: You must have a network interface for the back-channel network, plus one for each internal network. If you have two interfaces for each network, we will setup bonds for redundancy automatically.]]></key> |
||||
<key name="striker_0013">Next</key> |
||||
<key name="striker_0014">Step 1</key> |
||||
<key name="striker_0015">IFN Count</key> |
||||
<key name="striker_0016">Host name</key> |
||||
<key name="striker_0017">This is the hostname for this Striker dashboard. Generally it is a good idea to stick with the default.</key> |
||||
<key name="striker_0018">Back-Channel Network link #!variable!number!#</key> |
||||
<key name="striker_0019">This is where you configure the network to enable access this Back-Channel Network.</key> |
||||
<key name="striker_0020">Storage Network link #!variable!number!#</key> |
||||
<key name="striker_0021">This is where you configure the network to enable access this Storage Network.</key> |
||||
<key name="striker_0022">Internet-Facing Network link #!variable!number!#</key> |
||||
<key name="striker_0023">This is where you configure the network to enable access this Internet-Facing Network.</key> |
||||
<key name="striker_0024">IP Address</key> |
||||
<key name="striker_0025">Subnet</key> |
||||
<key name="striker_0026">Gateway</key> |
||||
<key name="striker_0027">DNS Server</key> |
||||
<key name="striker_0028">Network Interface</key> |
||||
<key name="striker_0029">Primary Interface</key> |
||||
<key name="striker_0030">Backup Interface</key> |
||||
<key name="striker_0031">Striker user name</key> |
||||
<key name="striker_0032">This is the user name that you will log into Striker as and the name of the user that owns the database.</key> |
||||
<key name="striker_0033">Striker password</key> |
||||
<key name="striker_0034"><![CDATA[This will be the password used to log into this Striker and connect to its database. It must be 6+ characters long.<br /><b>NOTE</b>: This password needs to be stored in plain text. Do not use a password you use elsewhere.]]></key> |
||||
<key name="striker_0035">Gateway</key> |
||||
<key name="striker_0036">This is the network gateway used to access the outside world.</key> |
||||
<key name="striker_0037">DNS</key> |
||||
<key name="striker_0038">This is the domain name server(s) to use when resolving domain names. You can specify 2 or more, separated by commas.</key> |
||||
<key name="striker_0039">Gateway Interface</key> |
||||
<key name="striker_0040">This is the interface with the internet access. Usually this is "ifn_link1".</key> <!-- Translation note; leave 'ifn_link1' as it is, it is the device name. --> |
||||
<key name="striker_0041">We're almost ready! Does this look right? If so, we'll setup this Striker dashboard.</key> |
||||
<key name="striker_0042">What we are planning to do...</key> |
||||
<key name="striker_0043">Apply New Configuration</key> |
||||
|
||||
<!-- Warnings --> |
||||
<key name="striker_warning_0001">The IP address will change. You will need to reconnect after applying these changes.</key> |
||||
|
||||
<!-- Errors --> |
||||
<key name="striker_error_0001">There are not enough network interfaces on this machine. You have: [#!variable!interface_count!#] interface(s), and you need at least: [#!variable!required_interfaces_for_single!#] interfaces to connect to the requested networks (one for Back-Channel and one for each Internet-Facing network).</key> |
||||
<key name="striker_error_0002">The local system UUID can't be read yet. This might be because the system is brand new and/or ScanCore hasn't run yet. Please try again in a minute.</key> |
||||
<key name="striker_error_0003">None of the databases are accessible, unable to proceed.</key> |
||||
<key name="striker_error_0004">The gateway address doesn't match any of your networks.</key> |
||||
|
||||
<!-- These are works and strings used by javascript/jqery --> |
||||
<key name="js_0001">Up</key> |
||||
<key name="js_0002">Down</key> |
||||
<key name="js_0003">Mbps</key> |
||||
|
||||
</language> |
||||
<!-- 日本語 --> |
||||
<language name="jp" long_name="日本語" description="Striker/ScanCore language file."> |
||||
|
||||
<key name="brand_0001">アルティーブ</key> |
||||
<key name="brand_0002">Anvil!</key> |
||||
<key name="brand_0003">ストライカ</key> |
||||
<key name="brand_0004">スカンコア</key> |
||||
<key name="brand_0005"><![CDATA[© 2017 <a href="https://alteeve.com/" target="_new">Alteeve's Niche! Inc.</a>, トロント、オンタリオ、カナダ]]></key> |
||||
|
||||
</language> |
||||
</words> |
@ -1,227 +0,0 @@ |
||||
-- This is the core database schema for ScanCore. |
||||
-- It builds on AN::Tools.sql. |
||||
|
||||
-- NOTE: network_interfaces, network_bonds and network_bridges are all used by scan-network (which doesn't |
||||
-- exist yet). |
||||
|
||||
-- This stores information about network interfaces on hosts. It is mainly used to match a MAC address to a |
||||
-- host. Given that it is possible that network devices can move, the linkage to the host_uuid can change. |
||||
CREATE TABLE network_interfaces ( |
||||
network_interface_uuid uuid not null primary key, |
||||
network_interface_host_uuid uuid not null, |
||||
network_interface_mac_address text not null, |
||||
network_interface_name text not null, -- This is the current name of the interface. |
||||
network_interface_speed bigint not null, -- This is the speed, in bits-per-second, of the interface. |
||||
network_interface_mtu bigint, -- This is the MTU (Maximum Transmitable Size), in bytes, for this interface. |
||||
network_interface_link_state text not null, -- 0 or 1 |
||||
network_interface_operational text not null, -- This is 'up', 'down' or 'unknown' |
||||
network_interface_duplex text not null, -- This is 'full', 'half' or 'unknown' |
||||
network_interface_medium text, -- This is 'tp' (twisted pair), 'fiber' or whatever they invent in the future. |
||||
network_interface_bond_uuid uuid, -- If this iface is in a bond, this will contain the 'bonds -> bond_uuid' that it is slaved to. |
||||
network_interface_bridge_uuid uuid, -- If this iface is attached to a bridge, this will contain the 'bridgess -> bridge_uuid' that it is connected to. |
||||
modified_date timestamp with time zone not null |
||||
); |
||||
ALTER TABLE network_interfaces OWNER TO #!variable!user!#; |
||||
|
||||
CREATE TABLE history.network_interfaces ( |
||||
history_id bigserial, |
||||
network_interface_uuid uuid not null, |
||||
network_interface_host_uuid uuid, |
||||
network_interface_mac_address text, |
||||
network_interface_name text, |
||||
network_interface_speed bigint, |
||||
network_interface_mtu bigint, |
||||
network_interface_link_state text, |
||||
network_interface_operational text, |
||||
network_interface_duplex text, |
||||
network_interface_medium text, |
||||
network_interface_bond_uuid uuid, |
||||
network_interface_bridge_uuid uuid, |
||||
modified_date timestamp with time zone not null |
||||
); |
||||
ALTER TABLE history.network_interfaces OWNER TO #!variable!user!#; |
||||
|
||||
CREATE FUNCTION history_network_interfaces() RETURNS trigger |
||||
AS $$ |
||||
DECLARE |
||||
history_network_interfaces RECORD; |
||||
BEGIN |
||||
SELECT INTO history_network_interfaces * FROM network_interfaces WHERE network_interface_host_uuid = new.network_interface_host_uuid; |
||||
INSERT INTO history.network_interfaces |
||||
(network_interface_uuid, |
||||
network_interface_host_uuid, |
||||
network_interface_mac_address, |
||||
network_interface_name, |
||||
network_interface_speed, |
||||
network_interface_mtu, |
||||
network_interface_link_state, |
||||
network_interface_operational, |
||||
network_interface_duplex, |
||||
network_interface_medium, |
||||
network_interface_bond_uuid, |
||||
network_interface_bridge_uuid, |
||||
modified_date) |
||||
VALUES |
||||
(history_network_interfaces.network_interface_uuid, |
||||
history_network_interfaces.network_interface_host_uuid, |
||||
history_network_interfaces.network_interface_mac_address, |
||||
history_network_interfaces.network_interface_name, |
||||
history_network_interfaces.network_interface_speed, |
||||
history_network_interfaces.network_interface_mtu, |
||||
history_network_interfaces.network_interface_link_state, |
||||
history_network_interfaces.network_interface_operational, |
||||
history_network_interfaces.network_interface_duplex, |
||||
history_network_interfaces.network_interface_medium, |
||||
history_network_interfaces.network_interface_bond_uuid, |
||||
history_network_interfaces.network_interface_bridge_uuid, |
||||
history_network_interfaces.modified_date); |
||||
RETURN NULL; |
||||
END; |
||||
$$ |
||||
LANGUAGE plpgsql; |
||||
ALTER FUNCTION history_network_interfaces() OWNER TO #!variable!user!#; |
||||
|
||||
CREATE TRIGGER trigger_network_interfaces |
||||
AFTER INSERT OR UPDATE ON network_interfaces |
||||
FOR EACH ROW EXECUTE PROCEDURE history_network_interfaces(); |
||||
|
||||
|
||||
-- This stores information about network bonds (mode=1) on a hosts. |
||||
CREATE TABLE bonds ( |
||||
bond_uuid uuid primary key, |
||||
bond_host_uuid uuid not null, |
||||
bond_name text not null, |
||||
bond_mode integer not null, -- This is the numerical bond type (will translate to the user's language in ScanCore) |
||||
bond_mtu bigint, |
||||
bond_primary_slave text, |
||||
bond_primary_reselect text, |
||||
bond_active_slave text, |
||||
bond_mii_status text, |
||||
bond_mii_polling_interval bigint, |
||||
bond_up_delay bigint, |
||||
bond_down_delay bigint, |
||||
modified_date timestamp with time zone not null, |
||||
|
||||
FOREIGN KEY(bond_host_uuid) REFERENCES hosts(host_uuid) |
||||
); |
||||
ALTER TABLE bonds OWNER TO #!variable!user!#; |
||||
|
||||
CREATE TABLE history.bonds ( |
||||
history_id bigserial, |
||||
bond_uuid uuid, |
||||
bond_host_uuid uuid, |
||||
bond_name text, |
||||
bond_mode integer, |
||||
bond_mtu bigint, |
||||
bond_primary_slave text, |
||||
bond_primary_reselect text, |
||||
bond_active_slave text, |
||||
bond_mii_status text, |
||||
bond_mii_polling_interval bigint, |
||||
bond_up_delay bigint, |
||||
bond_down_delay bigint, |
||||
modified_date timestamp with time zone not null |
||||
); |
||||
ALTER TABLE history.bonds OWNER TO #!variable!user!#; |
||||
|
||||
CREATE FUNCTION history_bonds() RETURNS trigger |
||||
AS $$ |
||||
DECLARE |
||||
history_bonds RECORD; |
||||
BEGIN |
||||
SELECT INTO history_bonds * FROM bonds WHERE bond_uuid=new.bond_uuid; |
||||
INSERT INTO history.bonds |
||||
(bond_uuid, |
||||
bond_host_uuid, |
||||
bond_name, |
||||
bond_mode, |
||||
bond_mtu, |
||||
bond_primary_slave, |
||||
bond_primary_reselect, |
||||
bond_active_slave, |
||||
bond_mii_status, |
||||
bond_mii_polling_interval, |
||||
bond_up_delay, |
||||
bond_down_delay, |
||||
modified_date) |
||||
VALUES |
||||
(history_bonds.bond_uuid, |
||||
history_bonds.bond_host_uuid, |
||||
history_bonds.bond_name, |
||||
history_bonds.bond_mode, |
||||
history_bonds.bond_mtu, |
||||
history_bonds.bond_primary_slave, |
||||
history_bonds.bond_primary_reselect, |
||||
history_bonds.bond_active_slave, |
||||
history_bonds.bond_mii_status, |
||||
history_bonds.bond_mii_polling_interval, |
||||
history_bonds.bond_up_delay, |
||||
history_bonds.bond_down_delay, |
||||
history_bonds.modified_date); |
||||
RETURN NULL; |
||||
END; |
||||
$$ |
||||
LANGUAGE plpgsql; |
||||
ALTER FUNCTION history_bonds() OWNER TO #!variable!user!#; |
||||
|
||||
CREATE TRIGGER trigger_bonds |
||||
AFTER INSERT OR UPDATE ON bonds |
||||
FOR EACH ROW EXECUTE PROCEDURE history_bonds(); |
||||
|
||||
|
||||
-- This stores information about network bridges. |
||||
CREATE TABLE bridges ( |
||||
bridge_uuid uuid primary key, |
||||
bridge_host_uuid uuid not null, |
||||
bridge_name text not null, |
||||
bridge_id text, |
||||
bridge_stp_enabled text, |
||||
modified_date timestamp with time zone not null, |
||||
|
||||
FOREIGN KEY(bridge_host_uuid) REFERENCES hosts(host_uuid) |
||||
); |
||||
ALTER TABLE bridges OWNER TO #!variable!user!#; |
||||
|
||||
CREATE TABLE history.bridges ( |
||||
history_id bigserial, |
||||
bridge_uuid uuid, |
||||
bridge_host_uuid uuid, |
||||
bridge_name text, |
||||
bridge_id text, |
||||
bridge_stp_enabled text, |
||||
modified_date timestamp with time zone not null |
||||
); |
||||
ALTER TABLE history.bridges OWNER TO #!variable!user!#; |
||||
|
||||
CREATE FUNCTION history_bridges() RETURNS trigger |
||||
AS $$ |
||||
DECLARE |
||||
history_bridges RECORD; |
||||
BEGIN |
||||
SELECT INTO history_bridges * FROM bridges WHERE bridge_uuid=new.bridge_uuid; |
||||
INSERT INTO history.bridges |
||||
(bridge_uuid, |
||||
bridge_host_uuid, |
||||
bridge_name, |
||||
bridge_name, |
||||
bridge_id, |
||||
bridge_stp_enabled, |
||||
modified_date) |
||||
VALUES |
||||
(history_bridges.bridge_uuid, |
||||
history_bridges.bridge_host_uuid, |
||||
history_bridges.bridge_name, |
||||
history_bridges.bridge_name, |
||||
history_bridges.bridge_id, |
||||
history_bridges.bridge_stp_enabled, |
||||
history_bridges.modified_date); |
||||
RETURN NULL; |
||||
END; |
||||
$$ |
||||
LANGUAGE plpgsql; |
||||
ALTER FUNCTION history_bridges() OWNER TO #!variable!user!#; |
||||
|
||||
CREATE TRIGGER trigger_bridges |
||||
AFTER INSERT OR UPDATE ON bridges |
||||
FOR EACH ROW EXECUTE PROCEDURE history_bridges(); |
||||
|
@ -1,32 +0,0 @@ |
||||
# This is the main Striker (and ScanCore) configuration file. |
||||
# |
||||
|
||||
database::1::host = 192.168.122.201 |
||||
database::1::port = 5432 |
||||
database::1::name = scancore |
||||
database::1::user = admin |
||||
database::1::password = Initial1 |
||||
database::1::ping_before_connect = 1 |
||||
|
||||
database::2::host = 192.168.122.202 |
||||
database::2::port = 5432 |
||||
database::2::name = scancore |
||||
database::2::user = admin |
||||
database::2::password = Initial1 |
||||
database::2::ping_before_connect = 1 |
||||
|
||||
# This is the schema for the ScanCore database. |
||||
sys::database::schema = /etc/scancore/scancore.sql |
||||
|
||||
# This puts a limit on how many queries (writes, generally) to make in a single batch transaction. This is |
||||
# useful when doing very large transacions, like resync'ing a large table, by limiting how long a given |
||||
# transaction can take and how much memory is used. |
||||
#sys::database::maximum_batch_size = 25000 |
||||
|
||||
# By default, we try to determine the host type using the host name. The rules used for this can be seen in |
||||
# 'perldoc AN::Tools::System -> determine_host_type'. If you are using non-standard host names, or for some |
||||
# other reason want to statically assign the host type, you can do so with this variable. Note that this sets |
||||
# the host type of this host only. You will need to set this appropriately on other hosts. |
||||
# |
||||
# Normally, you should not need to set this. |
||||
#sys::host_type = node |
@ -0,0 +1,15 @@ |
||||
#!/usr/bin/perl |
||||
# |
||||
use strict; |
||||
use warnings; |
||||
use Anvil::Tools; |
||||
|
||||
my $anvil = Anvil::Tools->new(); |
||||
$anvil->Log->level({set => 2}); |
||||
|
||||
# This is used to initialize the database |
||||
my $connections = $anvil->Database->connect(); |
||||
print "Connections: [$connections]\n"; |
||||
|
||||
|
||||
exit(0); |
@ -1,373 +0,0 @@ |
||||
#!/usr/bin/perl |
||||
# |
||||
# This checks the state of the postgresql database server and, if necessary, configures it for external |
||||
# access, initializes it and gets it running. |
||||
# |
||||
# Exit codes; |
||||
# 0 = Normal exit. |
||||
# 1 = Failed to initialize postgres |
||||
# 2 = Failed to start postgres |
||||
# 3 = ScanCore user not set in the local ID in striker.conf |
||||
# 4 = Failed to create the database user. |
||||
# 5 = |
||||
|
||||
use strict; |
||||
use warnings; |
||||
use Data::Dumper; |
||||
use AN::Tools; |
||||
|
||||
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; |
||||
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; |
||||
if (($running_directory =~ /^\./) && ($ENV{PWD})) |
||||
{ |
||||
$running_directory =~ s/^\./$ENV{PWD}/; |
||||
} |
||||
|
||||
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete. |
||||
$| = 1; |
||||
|
||||
my $an = AN::Tools->new(); |
||||
$an->Log->level({set => 2}); |
||||
$an->Log->secure({set => 1}); |
||||
|
||||
# Paths |
||||
$an->data->{path}{tools}{'an-prep-database'} = "/usr/sbin/striker/scancore-database"; |
||||
$an->data->{path}{tools}{'scancore-update-states'} = "/usr/sbin/striker/scancore-update-states"; |
||||
$an->data->{path}{config}{'striker.conf'} = "/etc/striker/striker.conf"; |
||||
|
||||
$an->Storage->read_config({file => $an->data->{path}{config}{'striker.conf'}}); |
||||
|
||||
my $local_id = $an->Database->get_local_id; |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { local_id => $local_id }}); |
||||
if ($local_id) |
||||
{ |
||||
# Start checks |
||||
my $running = $an->System->check_daemon({daemon => "postgresql"}); |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { running => $running }}); |
||||
if (not $running) |
||||
{ |
||||
# Do we need to initialize the databae? |
||||
if (not -e $an->data->{path}{configs}{'pg_hba.conf'}) |
||||
{ |
||||
# Initialize. |
||||
my $output = $an->System->call({shell_call => $an->data->{path}{exe}{'postgresql-setup'}." initdb", source => $THIS_FILE, line => __LINE__}); |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output }}); |
||||
|
||||
# Did it succeed? |
||||
if (not -e $an->data->{path}{configs}{'pg_hba.conf'}) |
||||
{ |
||||
# Failed... |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0001"}); |
||||
exit(1); |
||||
} |
||||
else |
||||
{ |
||||
# Initialized! |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0001"}); |
||||
} |
||||
|
||||
# Setup postgresql.conf |
||||
my $postgresql_backup = $an->data->{path}{directories}{backups}."/pgsql/postgresql.conf"; |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { postgresql_backup => $postgresql_backup }}); |
||||
$an->Storage->copy_file({source => $an->data->{path}{configs}{'postgresql.conf'}, target => $postgresql_backup}); |
||||
|
||||
my $postgresql_conf = $an->Storage->read_file({file => $an->data->{path}{configs}{'postgresql.conf'}}); |
||||
my $update_file = 1; |
||||
my $new_postgresql_conf = ""; |
||||
foreach my $line (split/\n/, $postgresql_conf) |
||||
{ |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { line => $line }}); |
||||
if ($line =~ /^listen_addresses = '\*'/) |
||||
{ |
||||
# No need to update. |
||||
$update_file = 0; |
||||
last; |
||||
} |
||||
elsif ($line =~ /^#listen_addresses = 'localhost'/) |
||||
{ |
||||
# Inject the new listen_addresses |
||||
$new_postgresql_conf .= "listen_addresses = '*'\n"; |
||||
} |
||||
$new_postgresql_conf .= $line."\n"; |
||||
} |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update_file => $update_file }}); |
||||
if ($update_file) |
||||
{ |
||||
$an->Storage->write_file({ |
||||
file => $an->data->{path}{configs}{'postgresql.conf'}, |
||||
body => $new_postgresql_conf, |
||||
user => "postgres", |
||||
group => "postgres", |
||||
mode => "0600", |
||||
overwrite => 1, |
||||
}); |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0002", variables => { file => $an->data->{path}{configs}{'postgresql.conf'} }}); |
||||
} |
||||
|
||||
# Setup pg_hba.conf now |
||||
my $pg_hba_backup = $an->data->{path}{directories}{backups}."/pgsql/pg_hba.conf"; |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { pg_hba_backup => $pg_hba_backup }}); |
||||
|
||||
$an->Storage->copy_file({source => $an->data->{path}{configs}{'pg_hba.conf'}, target => $pg_hba_backup}); |
||||
my $pg_hba_conf = $an->Storage->read_file({file => $an->data->{path}{configs}{'pg_hba.conf'}}); |
||||
$update_file = 1; |
||||
my $new_pg_hba_conf = ""; |
||||
foreach my $line (split/\n/, $pg_hba_conf) |
||||
{ |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { line => $line }}); |
||||
if ($line =~ /^host\s+all\s+all\s+\all\s+md5$/) |
||||
{ |
||||
# No need to update. |
||||
$update_file = 0; |
||||
last; |
||||
} |
||||
elsif ($line =~ /^# TYPE\s+DATABASE/) |
||||
{ |
||||
# Inject the new listen_addresses |
||||
$new_pg_hba_conf .= $line."\n"; |
||||
$new_pg_hba_conf .= "host\tall\t\tall\t\t*\t\t\tmd5\n"; |
||||
} |
||||
else |
||||
{ |
||||
$new_pg_hba_conf .= $line."\n"; |
||||
} |
||||
} |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update_file => $update_file }}); |
||||
if ($update_file) |
||||
{ |
||||
$an->Storage->write_file({ |
||||
file => $an->data->{path}{configs}{'pg_hba.conf'}, |
||||
body => $new_pg_hba_conf, |
||||
user => "postgres", |
||||
group => "postgres", |
||||
mode => "0600", |
||||
overwrite => 1, |
||||
}); |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0003", variables => { file => $an->data->{path}{configs}{'postgresql.conf'} }}); |
||||
} |
||||
} |
||||
|
||||
# Start the daemon. It might fail if it has never been initialized. |
||||
my $started = $an->System->start_daemon({daemon => "postgresql"}); |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { started => $started }}); |
||||
if ($started) |
||||
{ |
||||
# Started the daemon. |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0004"}); |
||||
} |
||||
else |
||||
{ |
||||
# Failed to start |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0002"}); |
||||
exit(2); |
||||
} |
||||
} |
||||
|
||||
# Create the .pgpass file, if needed. |
||||
my $created_pgpass = 0; |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { |
||||
'path::secure::postgres_pgpass' => $an->data->{path}{secure}{postgres_pgpass}, |
||||
"database::${local_id}::password" => $an->data->{database}{$local_id}{password}, |
||||
}}); |
||||
if ((not -e $an->data->{path}{secure}{postgres_pgpass}) && ($an->data->{database}{$local_id}{password})) |
||||
{ |
||||
my $body = "*:*:*:postgres:".$an->data->{database}{$local_id}{password}."\n"; |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { body => $body }}); |
||||
$an->Storage->write_file({ |
||||
file => $an->data->{path}{secure}{postgres_pgpass}, |
||||
body => $body, |
||||
user => "postgres", |
||||
group => "postgres", |
||||
mode => "0600", |
||||
overwrite => 1, |
||||
secure => 1, |
||||
}); |
||||
if (-e $an->data->{path}{secure}{postgres_pgpass}) |
||||
{ |
||||
$created_pgpass = 1; |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { created_pgpass => $created_pgpass }}); |
||||
} |
||||
} |
||||
|
||||
# Does the database user exist? |
||||
my $create_user = 1; |
||||
my $scancore_user = $an->data->{database}{$local_id}{user}; |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scancore_user => $scancore_user }}); |
||||
if (not $scancore_user) |
||||
{ |
||||
# No database user defined |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0003", variables => { id => $local_id }}); |
||||
exit(3); |
||||
} |
||||
my $user_list = $an->System->call({shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{psql}." template1 -c 'SELECT usename, usesysid FROM pg_catalog.pg_user;'\"", source => $THIS_FILE, line => __LINE__}); |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { user_list => $user_list }}); |
||||
foreach my $line (split/\n/, $user_list) |
||||
{ |
||||
if ($line =~ /^ $scancore_user\s+\|\s+(\d+)/) |
||||
{ |
||||
# User exists already |
||||
my $id = $1; |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0005", variables => { user => $scancore_user, id => $id }}); |
||||
$create_user = 0; |
||||
last; |
||||
} |
||||
} |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { create_user => $create_user }}); |
||||
if ($create_user) |
||||
{ |
||||
# Create the user |
||||
my $create_output = $an->System->call({shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{createuser}." --no-superuser --createdb --no-createrole $scancore_user\"", source => $THIS_FILE, line => __LINE__}); |
||||
my $user_list = $an->System->call({shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{psql}." template1 -c 'SELECT usename, usesysid FROM pg_catalog.pg_user;'\"", source => $THIS_FILE, line => __LINE__}); |
||||
my $user_exists = 0; |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { create_output => $create_output, user_list => $user_list }}); |
||||
foreach my $line (split/\n/, $user_list) |
||||
{ |
||||
if ($line =~ /^ $scancore_user\s+\|\s+(\d+)/) |
||||
{ |
||||
# Success! |
||||
my $id = $1; |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0006", variables => { user => $scancore_user, id => $id }}); |
||||
$user_exists = 1; |
||||
last; |
||||
} |
||||
} |
||||
if (not $user_exists) |
||||
{ |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0004", variables => { user => $scancore_user }}); |
||||
exit(4); |
||||
} |
||||
|
||||
# Update/set the passwords. |
||||
if ($an->data->{database}{$local_id}{password}) |
||||
{ |
||||
foreach my $user ("postgres", $scancore_user) |
||||
{ |
||||
my $update_output = $an->System->call({secure => 1, shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{psql}." template1 -c \\\"ALTER ROLE $user WITH PASSWORD '".$an->data->{database}{$local_id}{password}."';\\\"\"", source => $THIS_FILE, line => __LINE__}); |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { update_output => $update_output }}); |
||||
foreach my $line (split/\n/, $user_list) |
||||
{ |
||||
if ($line =~ /ALTER ROLE/) |
||||
{ |
||||
# Password set |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0007", variables => { user => $user }}); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
# Create the database, if needed. |
||||
my $create_database = 1; |
||||
my $scancore_database = $an->data->{database}{$local_id}{name}; |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "database::${local_id}::name" => $an->data->{database}{$local_id}{name} }}); |
||||
|
||||
my $database_list = $an->System->call({shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{psql}." template1 -c 'SELECT datname FROM pg_catalog.pg_database;'\"", source => $THIS_FILE, line => __LINE__}); |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { database_list => $database_list }}); |
||||
foreach my $line (split/\n/, $database_list) |
||||
{ |
||||
if ($line =~ /^ $scancore_database$/) |
||||
{ |
||||
# Database already exists. |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0008", variables => { database => $scancore_database }}); |
||||
$create_database = 0; |
||||
last; |
||||
} |
||||
} |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { create_database => $create_database }}); |
||||
if ($create_database) |
||||
{ |
||||
my $create_output = $an->System->call({shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{createdb}." --owner $scancore_user $scancore_database\"", source => $THIS_FILE, line => __LINE__}); |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { create_output => $create_output }}); |
||||
|
||||
my $database_exists = 0; |
||||
my $database_list = $an->System->call({shell_call => $an->data->{path}{exe}{su}." - postgres -c \"".$an->data->{path}{exe}{psql}." template1 -c 'SELECT datname FROM pg_catalog.pg_database;'\"", source => $THIS_FILE, line => __LINE__}); |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { database_list => $database_list }}); |
||||
foreach my $line (split/\n/, $database_list) |
||||
{ |
||||
if ($line =~ /^ $scancore_database$/) |
||||
{ |
||||
# Database created |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0008", variables => { database => $scancore_database }}); |
||||
$database_exists = 1; |
||||
last; |
||||
} |
||||
} |
||||
if (not $database_exists) |
||||
{ |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0005", variables => { database => $scancore_database }}); |
||||
exit(5); |
||||
} |
||||
} |
||||
|
||||
# Remove the temporary password file. |
||||
if (($created_pgpass) && (-e $an->data->{path}{secure}{postgres_pgpass})) |
||||
{ |
||||
unlink $an->data->{path}{secure}{postgres_pgpass}; |
||||
if (-e $an->data->{path}{secure}{postgres_pgpass}) |
||||
{ |
||||
# Failed to unlink the file. |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "warning_0001"}); |
||||
} |
||||
} |
||||
|
||||
##################################################################################################### |
||||
# NOTE: Below here is stuff that is for general setup. If it grows, we'll have to rename this tool. # |
||||
##################################################################################################### |
||||
|
||||
### TODO: This will need to set the proper SELinux context. |
||||
# Apache run scripts can't call the system UUID, so we'll write it to a text file. |
||||
if (not -e $an->data->{path}{data}{host_uuid}) |
||||
{ |
||||
$an->Storage->write_file({ |
||||
file => $an->data->{path}{data}{host_uuid}, |
||||
body => $an->Get->host_uuid, |
||||
user => "apache", |
||||
group => "apache", |
||||
mode => "0666", |
||||
overwrite => 0, |
||||
}); |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0011", variables => { file => $an->data->{path}{configs}{'postgresql.conf'} }}); |
||||
} |
||||
|
||||
# Log level 3 creates so much logging that it hits journald's rate limiting (1000 logs per 30 |
||||
# seconds). So we need to disable it. |
||||
if (not -e $an->data->{path}{configs}{'journald_an'}) |
||||
{ |
||||
# Write the file to disable journald rate limiting. |
||||
my $body = "# This disables the rate limiting so that when log level is set to 3, log |
||||
# entries aren't lost. If you want to override this, don't delete the file, |
||||
# just comment out the lines below. |
||||
|
||||
[Journal] |
||||
RateLimitInterval=0 |
||||
RateLimitBurst=0 |
||||
"; |
||||
$an->Storage->write_file({ |
||||
file => $an->data->{path}{configs}{'journald_an'}, |
||||
body => $body, |
||||
user => "root", |
||||
group => "root", |
||||
mode => "0644", |
||||
overwrite => 0, |
||||
}); |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0012", variables => { file => $an->data->{path}{configs}{'journald_an'} }}); |
||||
|
||||
my $shell_call = $an->data->{path}{exe}{systemctl}." restart systemd-journald.service"; |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); |
||||
|
||||
my $output = $an->System->call({shell_call => $shell_call, source => $THIS_FILE, line => __LINE__}); |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output }}); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
# Didn't find an entry for this machine. |
||||
$an->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0010"}); |
||||
} |
||||
|
||||
exit(0); |
||||
|
||||
|
||||
############################################################################################################# |
||||
# Functions # |
||||
############################################################################################################# |
@ -0,0 +1,101 @@ |
||||
#!/usr/bin/perl |
||||
# |
||||
# This is the master daemon that manages all periodically run processes on Striker dashboards and Anvil! |
||||
# nodes. |
||||
# |
||||
# TODO: At somepoint, we'll need to have a mechanism to fire off processes that might take a long time. |
||||
# |
||||
use strict; |
||||
use warnings; |
||||
use Anvil::Tools; |
||||
|
||||
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; |
||||
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; |
||||
if (($running_directory =~ /^\./) && ($ENV{PWD})) |
||||
{ |
||||
$running_directory =~ s/^\./$ENV{PWD}/; |
||||
} |
||||
|
||||
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete. |
||||
$| = 1; |
||||
|
||||
my $anvil = Anvil::Tools->new(); |
||||
$$anvil->Log->level({set => 2}); |
||||
|
||||
# Paths |
||||
$$anvil->data->{path}{tools}{'an-prep-database'} = "/usr/sbin/striker/an-prep-database"; |
||||
$$anvil->data->{path}{tools}{'scancore-update-states'} = "/usr/sbin/striker/scancore-update-states"; |
||||
$$anvil->data->{path}{config}{'striker.conf'} = "/etc/striker/striker.conf"; |
||||
|
||||
# Read our config. |
||||
$$anvil->Storage->read_config({file => $$anvil->data->{path}{config}{'striker.conf'}}); |
||||
|
||||
# There are some things we only want to run on (re)start and don't need to always run. |
||||
run_once($anvil); |
||||
|
||||
# These are the things we always want running. |
||||
while(1) |
||||
{ |
||||
# Loop and sleep for 2s. |
||||
keep_running($anvil); |
||||
|
||||
|
||||
# Exit if called with '--run-once' |
||||
if ($$anvil->data->{switches}{'run-once'}) |
||||
{ |
||||
$$anvil->nice_exit({code => 0}); |
||||
} |
||||
sleep 2; |
||||
} |
||||
|
||||
$$anvil->nice_exit({code => 0}); |
||||
|
||||
############################################################################################################# |
||||
# Functions # |
||||
############################################################################################################# |
||||
|
||||
# These are tools that don't need to constantly run. |
||||
sub run_once |
||||
{ |
||||
my ($anvil) = @_; |
||||
|
||||
# Check that the database is ready. |
||||
my $shell_call = $$anvil->data->{path}{tools}{'an-prep-database'}; |
||||
$$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); |
||||
my $database_output = $$anvil->System->call({shell_call => $shell_call, source => $THIS_FILE, line => __LINE__}); |
||||
if ($database_output) |
||||
{ |
||||
$$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { database_output => $database_output }}); |
||||
} |
||||
|
||||
return(0); |
||||
} |
||||
|
||||
# These are tools that need to keep running. |
||||
sub keep_running |
||||
{ |
||||
my ($anvil) = @_; |
||||
|
||||
# Update hardware state files. |
||||
update_state_file($anvil); |
||||
|
||||
return(0); |
||||
} |
||||
|
||||
# This calls 'scancore-update-states' which will scan the local machine's state (hardware and software) and |
||||
# record write it out to an HTML file |
||||
sub update_state_file |
||||
{ |
||||
my ($anvil) = @_; |
||||
|
||||
my $shell_call = $$anvil->data->{path}{tools}{'scancore-update-states'}; |
||||
$$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); |
||||
|
||||
my $states_output = $$anvil->System->call({shell_call => $shell_call, source => $THIS_FILE, line => __LINE__}); |
||||
if ($states_output) |
||||
{ |
||||
$$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { states_output => $states_output }}); |
||||
} |
||||
|
||||
return(0); |
||||
} |
@ -0,0 +1,370 @@ |
||||
#!/usr/bin/perl |
||||
# |
||||
# This checks the state of the postgresql database server and, if necessary, configures it for external |
||||
# access, initializes it and gets it running. |
||||
# |
||||
# Exit codes; |
||||
# 0 = Normal exit. |
||||
# 1 = Failed to initialize postgres |
||||
# 2 = Failed to start postgres |
||||
# 3 = ScanCore user not set in the local ID in striker.conf |
||||
# 4 = Failed to create the database user. |
||||
# 5 = |
||||
|
||||
use strict; |
||||
use warnings; |
||||
use Data::Dumper; |
||||
use Anvil::Tools; |
||||
|
||||
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; |
||||
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; |
||||
if (($running_directory =~ /^\./) && ($ENV{PWD})) |
||||
{ |
||||
$running_directory =~ s/^\./$ENV{PWD}/; |
||||
} |
||||
|
||||
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete. |
||||
$| = 1; |
||||
|
||||
my $anvil = Anvil::Tools->new(); |
||||
$anvil->Log->level({set => 2}); |
||||
$anvil->Log->secure({set => 1}); |
||||
|
||||
# Paths |
||||
$anvil->data->{path}{config}{'striker.conf'} = "/etc/anvil/anvil.conf"; |
||||
$anvil->Storage->read_config({file => $anvil->data->{path}{config}{'striker.conf'}}); |
||||
|
||||
my $local_id = $anvil->Database->get_local_id; |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { local_id => $local_id }}); |
||||
if ($local_id) |
||||
{ |
||||
# Start checks |
||||
my $running = $anvil->System->check_daemon({daemon => "postgresql"}); |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { running => $running }}); |
||||
if (not $running) |
||||
{ |
||||
# Do we need to initialize the databae? |
||||
if (not -e $anvil->data->{path}{configs}{'pg_hba.conf'}) |
||||
{ |
||||
# Initialize. |
||||
my $output = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{'postgresql-setup'}." initdb", source => $THIS_FILE, line => __LINE__}); |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output }}); |
||||
|
||||
# Did it succeed? |
||||
if (not -e $anvil->data->{path}{configs}{'pg_hba.conf'}) |
||||
{ |
||||
# Failed... |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0001"}); |
||||
exit(1); |
||||
} |
||||
else |
||||
{ |
||||
# Initialized! |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0001"}); |
||||
} |
||||
|
||||
# Setup postgresql.conf |
||||
my $postgresql_backup = $anvil->data->{path}{directories}{backups}."/pgsql/postgresql.conf"; |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { postgresql_backup => $postgresql_backup }}); |
||||
$anvil->Storage->copy_file({source => $anvil->data->{path}{configs}{'postgresql.conf'}, target => $postgresql_backup}); |
||||
|
||||
my $postgresql_conf = $anvil->Storage->read_file({file => $anvil->data->{path}{configs}{'postgresql.conf'}}); |
||||
my $update_file = 1; |
||||
my $new_postgresql_conf = ""; |
||||
foreach my $line (split/\n/, $postgresql_conf) |
||||
{ |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { line => $line }}); |
||||
if ($line =~ /^listen_addresses = '\*'/) |
||||
{ |
||||
# No need to update. |
||||
$update_file = 0; |
||||
last; |
||||
} |
||||
elsif ($line =~ /^#listen_addresses = 'localhost'/) |
||||
{ |
||||
# Inject the new listen_addresses |
||||
$new_postgresql_conf .= "listen_addresses = '*'\n"; |
||||
} |
||||
$new_postgresql_conf .= $line."\n"; |
||||
} |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update_file => $update_file }}); |
||||
if ($update_file) |
||||
{ |
||||
$anvil->Storage->write_file({ |
||||
file => $anvil->data->{path}{configs}{'postgresql.conf'}, |
||||
body => $new_postgresql_conf, |
||||
user => "postgres", |
||||
group => "postgres", |
||||
mode => "0600", |
||||
overwrite => 1, |
||||
}); |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0002", variables => { file => $anvil->data->{path}{configs}{'postgresql.conf'} }}); |
||||
} |
||||
|
||||
# Setup pg_hba.conf now |
||||
my $pg_hba_backup = $anvil->data->{path}{directories}{backups}."/pgsql/pg_hba.conf"; |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { pg_hba_backup => $pg_hba_backup }}); |
||||
|
||||
$anvil->Storage->copy_file({source => $anvil->data->{path}{configs}{'pg_hba.conf'}, target => $pg_hba_backup}); |
||||
my $pg_hba_conf = $anvil->Storage->read_file({file => $anvil->data->{path}{configs}{'pg_hba.conf'}}); |
||||
$update_file = 1; |
||||
my $new_pg_hba_conf = ""; |
||||
foreach my $line (split/\n/, $pg_hba_conf) |
||||
{ |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { line => $line }}); |
||||
if ($line =~ /^host\s+all\s+all\s+\all\s+md5$/) |
||||
{ |
||||
# No need to update. |
||||
$update_file = 0; |
||||
last; |
||||
} |
||||
elsif ($line =~ /^# TYPE\s+DATABASE/) |
||||
{ |
||||
# Inject the new listen_addresses |
||||
$new_pg_hba_conf .= $line."\n"; |
||||
$new_pg_hba_conf .= "host\tall\t\tall\t\t*\t\t\tmd5\n"; |
||||
} |
||||
else |
||||
{ |
||||
$new_pg_hba_conf .= $line."\n"; |
||||
} |
||||
} |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update_file => $update_file }}); |
||||
if ($update_file) |
||||
{ |
||||
$anvil->Storage->write_file({ |
||||
file => $anvil->data->{path}{configs}{'pg_hba.conf'}, |
||||
body => $new_pg_hba_conf, |
||||
user => "postgres", |
||||
group => "postgres", |
||||
mode => "0600", |
||||
overwrite => 1, |
||||
}); |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0003", variables => { file => $anvil->data->{path}{configs}{'postgresql.conf'} }}); |
||||
} |
||||
} |
||||
|
||||
# Start the daemon. It might fail if it has never been initialized. |
||||
my $started = $anvil->System->start_daemon({daemon => "postgresql"}); |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { started => $started }}); |
||||
if ($started) |
||||
{ |
||||
# Started the daemon. |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0004"}); |
||||
} |
||||
else |
||||
{ |
||||
# Failed to start |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0002"}); |
||||
exit(2); |
||||
} |
||||
} |
||||
|
||||
# Create the .pgpass file, if needed. |
||||
my $created_pgpass = 0; |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { |
||||
'path::secure::postgres_pgpass' => $anvil->data->{path}{secure}{postgres_pgpass}, |
||||
"database::${local_id}::password" => $anvil->data->{database}{$local_id}{password}, |
||||
}}); |
||||
if ((not -e $anvil->data->{path}{secure}{postgres_pgpass}) && ($anvil->data->{database}{$local_id}{password})) |
||||
{ |
||||
my $body = "*:*:*:postgres:".$anvil->data->{database}{$local_id}{password}."\n"; |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { body => $body }}); |
||||
$anvil->Storage->write_file({ |
||||
file => $anvil->data->{path}{secure}{postgres_pgpass}, |
||||
body => $body, |
||||
user => "postgres", |
||||
group => "postgres", |
||||
mode => "0600", |
||||
overwrite => 1, |
||||
secure => 1, |
||||
}); |
||||
if (-e $anvil->data->{path}{secure}{postgres_pgpass}) |
||||
{ |
||||
$created_pgpass = 1; |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { created_pgpass => $created_pgpass }}); |
||||
} |
||||
} |
||||
|
||||
# Does the database user exist? |
||||
my $create_user = 1; |
||||
my $scancore_user = $anvil->data->{database}{$local_id}{user}; |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scancore_user => $scancore_user }}); |
||||
if (not $scancore_user) |
||||
{ |
||||
# No database user defined |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0003", variables => { id => $local_id }}); |
||||
exit(3); |
||||
} |
||||
my $user_list = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{su}." - postgres -c \"".$anvil->data->{path}{exe}{psql}." template1 -c 'SELECT usename, usesysid FROM pg_catalog.pg_user;'\"", source => $THIS_FILE, line => __LINE__}); |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { user_list => $user_list }}); |
||||
foreach my $line (split/\n/, $user_list) |
||||
{ |
||||
if ($line =~ /^ $scancore_user\s+\|\s+(\d+)/) |
||||
{ |
||||
# User exists already |
||||
my $id = $1; |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0005", variables => { user => $scancore_user, id => $id }}); |
||||
$create_user = 0; |
||||
last; |
||||
} |
||||
} |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { create_user => $create_user }}); |
||||
if ($create_user) |
||||
{ |
||||
# Create the user |
||||
my $create_output = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{su}." - postgres -c \"".$anvil->data->{path}{exe}{createuser}." --no-superuser --createdb --no-createrole $scancore_user\"", source => $THIS_FILE, line => __LINE__}); |
||||
my $user_list = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{su}." - postgres -c \"".$anvil->data->{path}{exe}{psql}." template1 -c 'SELECT usename, usesysid FROM pg_catalog.pg_user;'\"", source => $THIS_FILE, line => __LINE__}); |
||||
my $user_exists = 0; |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { create_output => $create_output, user_list => $user_list }}); |
||||
foreach my $line (split/\n/, $user_list) |
||||
{ |
||||
if ($line =~ /^ $scancore_user\s+\|\s+(\d+)/) |
||||
{ |
||||
# Success! |
||||
my $id = $1; |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0006", variables => { user => $scancore_user, id => $id }}); |
||||
$user_exists = 1; |
||||
last; |
||||
} |
||||
} |
||||
if (not $user_exists) |
||||
{ |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0004", variables => { user => $scancore_user }}); |
||||
exit(4); |
||||
} |
||||
|
||||
# Update/set the passwords. |
||||
if ($anvil->data->{database}{$local_id}{password}) |
||||
{ |
||||
foreach my $user ("postgres", $scancore_user) |
||||
{ |
||||
my $update_output = $anvil->System->call({secure => 1, shell_call => $anvil->data->{path}{exe}{su}." - postgres -c \"".$anvil->data->{path}{exe}{psql}." template1 -c \\\"ALTER ROLE $user WITH PASSWORD '".$anvil->data->{database}{$local_id}{password}."';\\\"\"", source => $THIS_FILE, line => __LINE__}); |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, secure => 1, list => { update_output => $update_output }}); |
||||
foreach my $line (split/\n/, $user_list) |
||||
{ |
||||
if ($line =~ /ALTER ROLE/) |
||||
{ |
||||
# Password set |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0007", variables => { user => $user }}); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
# Create the database, if needed. |
||||
my $create_database = 1; |
||||
my $scancore_database = $anvil->data->{database}{$local_id}{name}; |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "database::${local_id}::name" => $anvil->data->{database}{$local_id}{name} }}); |
||||
|
||||
my $database_list = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{su}." - postgres -c \"".$anvil->data->{path}{exe}{psql}." template1 -c 'SELECT datname FROM pg_catalog.pg_database;'\"", source => $THIS_FILE, line => __LINE__}); |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { database_list => $database_list }}); |
||||
foreach my $line (split/\n/, $database_list) |
||||
{ |
||||
if ($line =~ /^ $scancore_database$/) |
||||
{ |
||||
# Database already exists. |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0008", variables => { database => $scancore_database }}); |
||||
$create_database = 0; |
||||
last; |
||||
} |
||||
} |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { create_database => $create_database }}); |
||||
if ($create_database) |
||||
{ |
||||
my $create_output = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{su}." - postgres -c \"".$anvil->data->{path}{exe}{createdb}." --owner $scancore_user $scancore_database\"", source => $THIS_FILE, line => __LINE__}); |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { create_output => $create_output }}); |
||||
|
||||
my $database_exists = 0; |
||||
my $database_list = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{su}." - postgres -c \"".$anvil->data->{path}{exe}{psql}." template1 -c 'SELECT datname FROM pg_catalog.pg_database;'\"", source => $THIS_FILE, line => __LINE__}); |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { database_list => $database_list }}); |
||||
foreach my $line (split/\n/, $database_list) |
||||
{ |
||||
if ($line =~ /^ $scancore_database$/) |
||||
{ |
||||
# Database created |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0008", variables => { database => $scancore_database }}); |
||||
$database_exists = 1; |
||||
last; |
||||
} |
||||
} |
||||
if (not $database_exists) |
||||
{ |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "error_0005", variables => { database => $scancore_database }}); |
||||
exit(5); |
||||
} |
||||
} |
||||
|
||||
# Remove the temporary password file. |
||||
if (($created_pgpass) && (-e $anvil->data->{path}{secure}{postgres_pgpass})) |
||||
{ |
||||
unlink $anvil->data->{path}{secure}{postgres_pgpass}; |
||||
if (-e $anvil->data->{path}{secure}{postgres_pgpass}) |
||||
{ |
||||
# Failed to unlink the file. |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "alert", key => "warning_0001"}); |
||||
} |
||||
} |
||||
|
||||
##################################################################################################### |
||||
# NOTE: Below here is stuff that is for general setup. If it grows, we'll have to rename this tool. # |
||||
##################################################################################################### |
||||
|
||||
### TODO: This will need to set the proper SELinux context. |
||||
# Apache run scripts can't call the system UUID, so we'll write it to a text file. |
||||
if (not -e $anvil->data->{path}{data}{host_uuid}) |
||||
{ |
||||
$anvil->Storage->write_file({ |
||||
file => $anvil->data->{path}{data}{host_uuid}, |
||||
body => $anvil->Get->host_uuid, |
||||
user => "apache", |
||||
group => "apache", |
||||
mode => "0666", |
||||
overwrite => 0, |
||||
}); |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0011", variables => { file => $anvil->data->{path}{configs}{'postgresql.conf'} }}); |
||||
} |
||||
|
||||
# Log level 3 creates so much logging that it hits journald's rate limiting (1000 logs per 30 |
||||
# seconds). So we need to disable it. |
||||
if (not -e $anvil->data->{path}{configs}{'journald_an'}) |
||||
{ |
||||
# Write the file to disable journald rate limiting. |
||||
my $body = "# This disables the rate limiting so that when log level is set to 3, log |
||||
# entries aren't lost. If you want to override this, don't delete the file, |
||||
# just comment out the lines below. |
||||
|
||||
[Journal] |
||||
RateLimitInterval=0 |
||||
RateLimitBurst=0 |
||||
"; |
||||
$anvil->Storage->write_file({ |
||||
file => $anvil->data->{path}{configs}{'journald_an'}, |
||||
body => $body, |
||||
user => "root", |
||||
group => "root", |
||||
mode => "0644", |
||||
overwrite => 0, |
||||
}); |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "message_0012", variables => { file => $anvil->data->{path}{configs}{'journald_an'} }}); |
||||
|
||||
my $shell_call = $anvil->data->{path}{exe}{systemctl}." restart systemd-journald.service"; |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { shell_call => $shell_call }}); |
||||
|
||||
my $output = $anvil->System->call({shell_call => $shell_call, source => $THIS_FILE, line => __LINE__}); |
||||
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output }}); |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
# Didn't find an entry for this machine. |
||||
$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "message_0010"}); |
||||
} |
||||
|
||||
exit(0); |
||||
|
||||
|
||||
############################################################################################################# |
||||
# Functions # |
||||
############################################################################################################# |
@ -1,87 +0,0 @@ |
||||
#!/usr/bin/perl |
||||
# |
||||
# This is the master daemon that manages all periodically run processes on Striker dashboards and Anvil! |
||||
# nodes. |
||||
# |
||||
use strict; |
||||
use warnings; |
||||
use AN::Tools; |
||||
|
||||
my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; |
||||
my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; |
||||
if (($running_directory =~ /^\./) && ($ENV{PWD})) |
||||
{ |
||||
$running_directory =~ s/^\./$ENV{PWD}/; |
||||
} |
||||
|
||||
# Turn off buffering so that the pinwheel will display while waiting for the SSH call(s) to complete. |
||||
$| = 1; |
||||
|
||||
my $an = AN::Tools->new(); |
||||
$an->Log->level({set => 2}); |
||||
|
||||
# Paths |
||||
$an->data->{path}{tools}{'scancore-database'} = "/usr/sbin/striker/scancore-database"; |
||||
$an->data->{path}{tools}{'scancore-update-states'} = "/usr/sbin/striker/scancore-update-states"; |
||||
$an->data->{path}{config}{'striker.conf'} = "/etc/striker/striker.conf"; |
||||
|
||||
# Read our config. |
||||
$an->Storage->read_config({file => $an->data->{path}{config}{'striker.conf'}}); |
||||
|
||||
# There are some things we only want to run on (re)start and don't need to always run. |
||||
run_once($an); |
||||
|
||||
# These are the things we always want running. |
||||
while(1) |
||||
{ |
||||
# Loop and sleep for 2s. |
||||
keep_running($an); |
||||
sleep 2; |
||||
} |
||||
|
||||
$an->nice_exit({code => 0}); |
||||
|
||||
############################################################################################################# |
||||
# Functions # |
||||
############################################################################################################# |
||||
|
||||
# These are tools that don't need to constantly run. |
||||
sub run_once |
||||
{ |
||||
my ($an) = @_; |
||||
|
||||
# Check that the database is ready. |
||||
my $database_output = $an->System->call({shell_call => $an->data->{path}{tools}{'scancore-database'}, source => $THIS_FILE, line => __LINE__}); |
||||
if ($database_output) |
||||
{ |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { database_output => $database_output }}); |
||||
} |
||||
|
||||
return(0); |
||||
} |
||||
|
||||
# These are tools that need to keep running. |
||||
sub keep_running |
||||
{ |
||||
my ($an) = @_; |
||||
|
||||
# Update hardware state files. |
||||
update_state_file($an); |
||||
|
||||
return(0); |
||||
} |
||||
|
||||
# This calls 'scancore-update-states' which will scan the local machine's state (hardware and software) and |
||||
# record write it out to an HTML file |
||||
sub update_state_file |
||||
{ |
||||
my ($an) = @_; |
||||
|
||||
my $states_output = $an->System->call({shell_call => $an->data->{path}{tools}{'scancore-update-states'}, source => $THIS_FILE, line => __LINE__}); |
||||
if ($states_output) |
||||
{ |
||||
$an->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { states_output => $states_output }}); |
||||
} |
||||
|
||||
return(0); |
||||
} |
@ -1,10 +1,10 @@ |
||||
[Unit] |
||||
Description=ScanCore - Anvil! IA Suite |
||||
Description=Anvil! Intelligent Availability Platform - main service daemon |
||||
Wants=network.target |
||||
|
||||
[Service] |
||||
Type=simple |
||||
ExecStart=/usr/sbin/striker/scancore-daemon |
||||
ExecStart=/usr/sbin/anvil/anvil-daemon |
||||
ExecStop=/bin/kill -WINCH ${MAINPID} |
||||
Restart=always |
||||
|
@ -0,0 +1 @@ |
||||
clear; journalctl -f -a -S "$(date +"%F %R:%S")" -t anvil |
Loading…
Reference in new issue