mirror of
https://github.com/xcat2/xcat-core.git
synced 2026-08-01 02:29:41 +00:00
Merge pull request #7647 from VersatusHPC/refactor/probe-netplan-command-capture
refactor(probe): reuse command capture for netplan
This commit is contained in:
@@ -160,16 +160,15 @@ sub get_os {
|
||||
|
||||
sub _netplan_get {
|
||||
my $key = shift;
|
||||
my $pid = open(my $fh, '-|');
|
||||
return unless defined $pid;
|
||||
if ($pid == 0) {
|
||||
open(STDERR, '>', '/dev/null');
|
||||
exec 'netplan', 'get', $key;
|
||||
exit 1;
|
||||
}
|
||||
my $val = <$fh>;
|
||||
close $fh;
|
||||
return if $?;
|
||||
my ($val, $error) = _capture_command(
|
||||
sub {
|
||||
my $fh = shift;
|
||||
return scalar <$fh>;
|
||||
},
|
||||
1,
|
||||
'netplan', 'get', $key
|
||||
);
|
||||
return if defined $error;
|
||||
chomp $val if defined $val;
|
||||
return $val;
|
||||
}
|
||||
@@ -183,8 +182,8 @@ sub _command_available {
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub _capture_command_output {
|
||||
my @command = @_;
|
||||
sub _capture_command {
|
||||
my ($read_output, $exec_failure_status, @command) = @_;
|
||||
my $pid = open(my $fh, '-|');
|
||||
unless (defined $pid) {
|
||||
my $error = "unable to start '$command[0]': $!";
|
||||
@@ -193,11 +192,10 @@ sub _capture_command_output {
|
||||
if ($pid == 0) {
|
||||
open(STDERR, '>', '/dev/null');
|
||||
exec @command;
|
||||
exit 127;
|
||||
exit $exec_failure_status;
|
||||
}
|
||||
|
||||
local $/;
|
||||
my $output = <$fh>;
|
||||
my $output = $read_output->($fh);
|
||||
close $fh;
|
||||
my $status = $?;
|
||||
if ($status) {
|
||||
@@ -213,6 +211,22 @@ sub _capture_command_output {
|
||||
return wantarray ? (undef, $error) : undef;
|
||||
}
|
||||
|
||||
return wantarray ? ($output, undef) : $output;
|
||||
}
|
||||
|
||||
sub _capture_command_output {
|
||||
my @command = @_;
|
||||
my ($output, $error) = _capture_command(
|
||||
sub {
|
||||
my $fh = shift;
|
||||
local $/;
|
||||
return scalar <$fh>;
|
||||
},
|
||||
127,
|
||||
@command
|
||||
);
|
||||
return wantarray ? (undef, $error) : undef if defined $error;
|
||||
|
||||
$output = '' unless defined $output;
|
||||
return wantarray ? ($output, undef) : $output;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use lib "$FindBin::Bin/../../xCAT-probe/lib/perl";
|
||||
|
||||
use File::Temp qw(tempdir);
|
||||
use Test::More;
|
||||
|
||||
require probe_utils;
|
||||
|
||||
sub write_file {
|
||||
my ($file, $contents) = @_;
|
||||
|
||||
open(my $fh, '>', $file) or die "Unable to write $file: $!";
|
||||
print $fh $contents;
|
||||
close $fh;
|
||||
}
|
||||
|
||||
sub read_file {
|
||||
my $file = shift;
|
||||
|
||||
open(my $fh, '<', $file) or die "Unable to read $file: $!";
|
||||
local $/;
|
||||
my $contents = <$fh>;
|
||||
close $fh;
|
||||
return $contents;
|
||||
}
|
||||
|
||||
my $fake_bin = tempdir(CLEANUP => 1);
|
||||
my $argv_file = "$fake_bin/argv";
|
||||
my $fake_netplan = "$fake_bin/netplan";
|
||||
|
||||
write_file($fake_netplan, <<'EOF');
|
||||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
open(my $fh, '>', $ENV{XCAT_TEST_NETPLAN_ARGV}) or die "Unable to record arguments: $!";
|
||||
print $fh join("\n", @ARGV), "\n";
|
||||
close $fh;
|
||||
|
||||
my $mode = $ENV{XCAT_TEST_NETPLAN_MODE} || '';
|
||||
if ($mode eq 'multiple-lines') {
|
||||
print "first line\nsecond line\n";
|
||||
} elsif ($mode eq 'continued-output') {
|
||||
local $| = 1;
|
||||
print "first line\n";
|
||||
local $SIG{PIPE} = 'IGNORE';
|
||||
for (1 .. 4096) {
|
||||
exit 7 unless print 'x' x 4096;
|
||||
}
|
||||
} elsif ($mode eq 'empty-first-line') {
|
||||
print "\nsecond line\n";
|
||||
} elsif ($mode eq 'no-trailing-newline') {
|
||||
print "single line";
|
||||
} elsif ($mode eq 'empty-output') {
|
||||
exit 0;
|
||||
} elsif ($mode eq 'failure') {
|
||||
print "ignored output\n";
|
||||
print STDERR "netplan get failed\n";
|
||||
exit 7;
|
||||
} else {
|
||||
die "Unknown test mode: $mode";
|
||||
}
|
||||
EOF
|
||||
chmod oct('755'), $fake_netplan;
|
||||
|
||||
local $ENV{PATH} = "$fake_bin:$ENV{PATH}";
|
||||
local $ENV{XCAT_TEST_NETPLAN_ARGV} = $argv_file;
|
||||
|
||||
{
|
||||
local $ENV{XCAT_TEST_NETPLAN_MODE} = 'multiple-lines';
|
||||
is(
|
||||
probe_utils::_netplan_get('ethernets.eth0.addresses'),
|
||||
'first line',
|
||||
'netplan get returns only the first output line'
|
||||
);
|
||||
is(
|
||||
read_file($argv_file),
|
||||
"get\nethernets.eth0.addresses\n",
|
||||
'netplan get receives the exact subcommand and key arguments'
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
local $ENV{XCAT_TEST_NETPLAN_MODE} = 'continued-output';
|
||||
ok(
|
||||
!defined(probe_utils::_netplan_get('ethernets.eth0')),
|
||||
'a command failure after the first line still returns undef'
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
local $ENV{XCAT_TEST_NETPLAN_MODE} = 'empty-first-line';
|
||||
is(
|
||||
probe_utils::_netplan_get('ethernets.eth0'),
|
||||
'',
|
||||
'an empty first line remains a defined empty value'
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
local $ENV{XCAT_TEST_NETPLAN_MODE} = 'no-trailing-newline';
|
||||
is(
|
||||
probe_utils::_netplan_get('ethernets.eth0'),
|
||||
'single line',
|
||||
'output without a trailing newline is preserved'
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
local $ENV{XCAT_TEST_NETPLAN_MODE} = 'empty-output';
|
||||
ok(
|
||||
!defined(probe_utils::_netplan_get('ethernets.eth0')),
|
||||
'successful empty output returns undef'
|
||||
);
|
||||
my @values = probe_utils::_netplan_get('ethernets.eth0');
|
||||
is(scalar(@values), 1, 'successful empty output returns one undef value in list context');
|
||||
ok(!defined($values[0]), 'the list-context empty-output value is undef');
|
||||
}
|
||||
|
||||
{
|
||||
local $ENV{XCAT_TEST_NETPLAN_MODE} = 'failure';
|
||||
ok(
|
||||
!defined(probe_utils::_netplan_get('ethernets.eth0')),
|
||||
'failed netplan get returns undef even when it writes output'
|
||||
);
|
||||
my @values = probe_utils::_netplan_get('ethernets.eth0');
|
||||
is(scalar(@values), 0, 'failed netplan get returns an empty list in list context');
|
||||
}
|
||||
|
||||
{
|
||||
my $missing_bin = tempdir(CLEANUP => 1);
|
||||
local $ENV{PATH} = $missing_bin;
|
||||
my $value = probe_utils::_netplan_get('ethernets.eth0');
|
||||
my $status = $?;
|
||||
|
||||
ok(!defined($value), 'netplan exec failure returns undef');
|
||||
is($status >> 8, 1, 'netplan exec failure preserves its original exit status');
|
||||
}
|
||||
|
||||
done_testing();
|
||||
Reference in New Issue
Block a user