mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-10-21 15:18:19 +00:00
228 lines
11 KiB
Perl
228 lines
11 KiB
Perl
#!/usr/bin/env perl
|
|
use strict;
|
|
use warnings;
|
|
|
|
use File::Copy qw(copy);
|
|
use File::Path qw(make_path);
|
|
use File::Slurper qw(read_text write_text);
|
|
use File::Spec;
|
|
use File::Temp qw(tempdir);
|
|
use FindBin;
|
|
use Fcntl qw(S_IMODE);
|
|
use lib "$FindBin::Bin/../lib";
|
|
use Test::More;
|
|
|
|
use XCAT::Test::File qw(repo_path slurp_repo_file);
|
|
use XCAT::Test::Process qw(run_command);
|
|
|
|
my $sync_helper = repo_path('build-utils/sync-xcat-apache-configs');
|
|
ok( -x $sync_helper, 'the Apache configuration sync helper is executable' );
|
|
is( system( 'sh', '-n', $sync_helper ), 0,
|
|
'the Apache configuration sync helper has POSIX shell syntax' );
|
|
|
|
my ( $status, $output ) = run_command( $sync_helper, '--check' );
|
|
is( $status, 0, 'the committed service-node configurations are current' )
|
|
or diag($output);
|
|
is( $output, '', 'a successful repository check is quiet' );
|
|
|
|
my @config_pairs = (
|
|
[ 'xCAT/xcat.conf', 'xCATsn/xcat.conf' ],
|
|
[ 'xCAT/xcat.conf.apach24', 'xCATsn/xcat.conf.apach24' ],
|
|
);
|
|
for my $pair (@config_pairs) {
|
|
my ( $source, $generated ) = @{$pair};
|
|
my $generated_path = repo_path($generated);
|
|
ok( !-l $generated_path, "$generated is a regular tracked file" );
|
|
is( slurp_repo_file($generated), slurp_repo_file($source),
|
|
"$generated is generated byte-for-byte from $source" );
|
|
is( sprintf( '%04o', S_IMODE( ( stat($generated_path) )[2] ) ), '0644',
|
|
"$generated has the required tracked mode" );
|
|
}
|
|
|
|
my $fixture_root = tempdir( CLEANUP => 1 );
|
|
my $fixture_helper = stage_sync_fixture($fixture_root);
|
|
write_text( File::Spec->catfile( $fixture_root, 'xCAT', 'xcat.conf' ),
|
|
"apache22 canonical\n" );
|
|
write_text( File::Spec->catfile( $fixture_root, 'xCAT', 'xcat.conf.apach24' ),
|
|
"apache24 canonical\n" );
|
|
write_text( File::Spec->catfile( $fixture_root, 'xCATsn', 'xcat.conf' ),
|
|
"apache22 stale\n" );
|
|
write_text( File::Spec->catfile( $fixture_root, 'xCATsn', 'xcat.conf.apach24' ),
|
|
"apache24 stale\n\n" );
|
|
|
|
( $status, $output ) = run_command( $fixture_helper, '--check' );
|
|
is( $status, 1, '--check rejects drift in generated configurations' );
|
|
like( $output, qr{^xCATsn/xcat\.conf is out of date;}m,
|
|
'--check identifies the stale Apache 2.2 copy' );
|
|
like( $output, qr{^xCATsn/xcat\.conf\.apach24 is out of date;}m,
|
|
'--check identifies the stale Apache 2.4 copy' );
|
|
|
|
( $status, $output ) = run_command( $fixture_helper, '--write' );
|
|
is( $status, 0, '--write refreshes generated configurations' )
|
|
or diag($output);
|
|
like( $output, qr{^updated xCATsn/xcat\.conf$}m,
|
|
'--write reports the refreshed Apache 2.2 copy' );
|
|
like( $output, qr{^updated xCATsn/xcat\.conf\.apach24$}m,
|
|
'--write reports the refreshed Apache 2.4 copy' );
|
|
|
|
for my $pair (@config_pairs) {
|
|
my ( $source, $generated ) = @{$pair};
|
|
my $source_path = File::Spec->catfile( $fixture_root, split( '/', $source ) );
|
|
my $generated_path =
|
|
File::Spec->catfile( $fixture_root, split( '/', $generated ) );
|
|
is( read_text($generated_path), read_text($source_path),
|
|
"--write makes $generated byte-identical to its canonical source" );
|
|
is( sprintf( '%04o', S_IMODE( ( stat($generated_path) )[2] ) ), '0644',
|
|
"--write gives $generated a deterministic file mode" );
|
|
}
|
|
|
|
( $status, $output ) = run_command( $fixture_helper, '--write' );
|
|
is( $status, 0, '--write accepts already-current configurations' );
|
|
is( $output, '', '--write does not rewrite or report current configurations' );
|
|
my $current_generated =
|
|
File::Spec->catfile( $fixture_root, 'xCATsn', 'xcat.conf' );
|
|
chmod 0600, $current_generated
|
|
or die "Unable to change $current_generated mode: $!";
|
|
( $status, $output ) = run_command( $fixture_helper, '--check' );
|
|
is( $status, 1, '--check rejects mode drift in generated configurations' );
|
|
like( $output, qr{^xCATsn/xcat\.conf is out of date;}m,
|
|
'--check identifies the generated configuration with mode drift' );
|
|
( $status, $output ) = run_command( $fixture_helper, '--write' );
|
|
is( $status, 0, '--write repairs mode drift on current configurations' );
|
|
is( sprintf( '%04o', S_IMODE( ( stat($current_generated) )[2] ) ), '0644',
|
|
'--write normalizes a current generated configuration to mode 0644' );
|
|
is( $output, '', 'mode-only repair does not report a content update' );
|
|
|
|
my $symlink_victim = File::Spec->catfile( $fixture_root, 'symlink-victim' );
|
|
write_text( $symlink_victim, "apache22 canonical\n" );
|
|
unlink($current_generated) or die "Unable to remove $current_generated: $!";
|
|
symlink( $symlink_victim, $current_generated )
|
|
or die "Unable to create $current_generated symlink: $!";
|
|
( $status, $output ) = run_command( $fixture_helper, '--check' );
|
|
is( $status, 1, '--check rejects a generated configuration symlink' );
|
|
like( $output, qr{^xCATsn/xcat\.conf is out of date;}m,
|
|
'--check identifies the generated configuration symlink' );
|
|
( $status, $output ) = run_command( $fixture_helper, '--write' );
|
|
is( $status, 0, '--write replaces a generated configuration symlink' );
|
|
ok( !-l $current_generated,
|
|
'--write leaves a regular generated configuration behind' );
|
|
is( read_text($current_generated), "apache22 canonical\n",
|
|
'--write restores canonical content after replacing a symlink' );
|
|
is( read_text($symlink_victim), "apache22 canonical\n",
|
|
'--write does not modify the former symlink target' );
|
|
|
|
my $missing_generated =
|
|
File::Spec->catfile( $fixture_root, 'xCATsn', 'xcat.conf.apach24' );
|
|
unlink($missing_generated) or die "Unable to remove $missing_generated: $!";
|
|
( $status, $output ) = run_command( $fixture_helper, '--check' );
|
|
is( $status, 1, '--check rejects a missing generated configuration' );
|
|
like( $output, qr{^xCATsn/xcat\.conf\.apach24 is out of date;}m,
|
|
'--check identifies the missing generated configuration' );
|
|
( $status, $output ) = run_command( $fixture_helper, '--write' );
|
|
is( $status, 0, '--write recreates a missing generated configuration' )
|
|
or diag($output);
|
|
is( read_text($missing_generated), "apache24 canonical\n",
|
|
'--write preserves the canonical final newline exactly' );
|
|
is( sprintf( '%04o', S_IMODE( ( stat($missing_generated) )[2] ) ), '0644',
|
|
'--write recreates a generated configuration with mode 0644' );
|
|
|
|
my $staging_directory = tempdir( CLEANUP => 1 );
|
|
my $staging_victim = File::Spec->catfile( $fixture_root, 'staging-victim' );
|
|
write_text( $staging_victim, "do not overwrite\n" );
|
|
symlink( $staging_victim,
|
|
File::Spec->catfile( $staging_directory, 'xcat.conf' ) )
|
|
or die 'Unable to create staging symlink fixture';
|
|
( $status, $output ) =
|
|
run_command( $fixture_helper, '--stage', $staging_directory );
|
|
is( $status, 0, '--stage copies canonical configurations for package builds' )
|
|
or diag($output);
|
|
is( $output, '', 'successful package staging is quiet' );
|
|
for my $name ( 'xcat.conf', 'xcat.conf.apach24' ) {
|
|
my $staged = File::Spec->catfile( $staging_directory, $name );
|
|
my $canonical = File::Spec->catfile( $fixture_root, 'xCAT', $name );
|
|
ok( !-l $staged, "--stage creates a regular $name file" );
|
|
is( read_text($staged), read_text($canonical),
|
|
"--stage copies canonical $name content" );
|
|
is( sprintf( '%04o', S_IMODE( ( stat($staged) )[2] ) ), '0644',
|
|
"--stage gives $name the required package mode" );
|
|
}
|
|
is( read_text($staging_victim), "do not overwrite\n",
|
|
'--stage replaces a destination symlink without touching its target' );
|
|
|
|
my $directory_target = File::Spec->catfile( $staging_directory, 'xcat.conf' );
|
|
unlink($directory_target) or die "Unable to remove $directory_target: $!";
|
|
mkdir($directory_target) or die "Unable to create $directory_target: $!";
|
|
( $status, $output ) =
|
|
run_command( $fixture_helper, '--stage', $staging_directory );
|
|
is( $status, 1, '--stage refuses to replace a destination directory' );
|
|
like( $output, qr{ cannot replace a directory$}m,
|
|
'--stage identifies the destination directory' );
|
|
rmdir($directory_target) or die "Unable to remove $directory_target: $!";
|
|
|
|
my $canonical_path = File::Spec->catfile( $fixture_root, 'xCAT', 'xcat.conf' );
|
|
my $canonical_contents = read_text($canonical_path);
|
|
my $canonical_symlink_target =
|
|
File::Spec->catfile( $fixture_root, 'canonical-symlink-target' );
|
|
write_text( $canonical_symlink_target, $canonical_contents );
|
|
unlink($canonical_path) or die "Unable to remove $canonical_path: $!";
|
|
symlink( $canonical_symlink_target, $canonical_path )
|
|
or die "Unable to create $canonical_path symlink: $!";
|
|
( $status, $output ) = run_command( $fixture_helper, '--check' );
|
|
is( $status, 1, '--check rejects a canonical configuration symlink' );
|
|
like( $output, qr{^xCAT/xcat\.conf must be a regular file$}m,
|
|
'--check identifies the canonical configuration symlink' );
|
|
unlink($canonical_path) or die "Unable to remove $canonical_path: $!";
|
|
write_text( $canonical_path, $canonical_contents );
|
|
|
|
for my $arguments (
|
|
[], ['--invalid'], [ '--check', '--write' ], ['--stage'],
|
|
[ '--stage', $staging_directory, 'extra' ]
|
|
)
|
|
{
|
|
( $status, $output ) = run_command( $fixture_helper, @{$arguments} );
|
|
is( $status, 2, 'invalid invocation exits with usage status 2' );
|
|
like( $output,
|
|
qr{^Usage: sync-xcat-apache-configs --check\|--write\|--stage DIRECTORY$}m,
|
|
'invalid invocation prints concise usage' );
|
|
}
|
|
( $status, $output ) = run_command( $fixture_helper, '--stage',
|
|
File::Spec->catdir( $fixture_root, 'missing-stage-directory' ) );
|
|
is( $status, 1, '--stage rejects a missing destination directory' );
|
|
like( $output, qr{ is not a directory$}m,
|
|
'--stage identifies the invalid destination directory' );
|
|
|
|
# The legacy `makerpm` half of this file went with makerpm itself; buildrpms.pl
|
|
# invokes build-utils/sync-xcat-apache-configs directly, and the helper's own
|
|
# behaviour is covered above.
|
|
|
|
my $management_debian = slurp_repo_file('xCAT/debian/install');
|
|
my $service_debian = slurp_repo_file('xCATsn/debian/install');
|
|
for my $manifest (
|
|
[ 'management', $management_debian ],
|
|
[ 'service-node', $service_debian ],
|
|
) {
|
|
my ( $label, $contents ) = @{$manifest};
|
|
like( $contents, qr{^xcat\.conf\s+etc/apache2/(?:conf\.d|conf-available)/?\s*$}m,
|
|
"$label Debian payload includes the Apache 2.2 configuration" );
|
|
like( $contents, qr{^xcat\.conf\.apach24\s+etc/apache2/(?:conf\.d|conf-available)/?\s*$}m,
|
|
"$label Debian payload includes the Apache 2.4 configuration" );
|
|
}
|
|
|
|
done_testing();
|
|
|
|
sub stage_sync_fixture {
|
|
my ($root) = @_;
|
|
make_path(
|
|
File::Spec->catdir( $root, 'build-utils' ),
|
|
File::Spec->catdir( $root, 'xCAT' ),
|
|
File::Spec->catdir( $root, 'xCATsn' ),
|
|
);
|
|
my $destination =
|
|
File::Spec->catfile( $root, 'build-utils', 'sync-xcat-apache-configs' );
|
|
copy( $sync_helper, $destination )
|
|
or die "Unable to stage the Apache configuration sync helper: $!";
|
|
chmod 0755, $destination
|
|
or die "Unable to make the staged sync helper executable: $!";
|
|
return $destination;
|
|
}
|