����JFIF��x�x����'
| Server IP : 78.140.185.180 / Your IP : 216.73.216.170 Web Server : LiteSpeed System : Linux cpanel13.v.fozzy.com 4.18.0-513.11.1.lve.el8.x86_64 #1 SMP Thu Jan 18 16:21:02 UTC 2024 x86_64 User : builderbox ( 1072) PHP Version : 7.3.33 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /proc/self/root/proc/self/root/proc/1630575/root/usr/lib64/nagios/plugins/extra/ |
Upload File : |
#!/usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
use Carp;
use JSON::XS;
use LWP::UserAgent;
use IPC::Run qw(run);
use Getopt::Long;
my ( $opt_c, $opt_h );
my $exitcode = '0';
GetOptions(
"c|containers=s" => \$opt_c,
"h|help" => \$opt_h,
);
if ($opt_h) {
my $help_text = <<"END";
Usage: $0 -c container1,container2,...
Checks the version for active docker containers and compares them to latest on DockerHub
-c|--containers List of local containers and image to check, separated by comma
Example: fe1_nginx:stable,dev2_gitlab
Default value for image tag is latest
-h|--help (--help) Show this help message
END
say $help_text;
exit;
}
croak 'List of containers not passed!' if !$opt_c;
my @incidents;
my %containers;
for ( split( ',', $opt_c ) ) {
$containers{ ( split ':', $_ )[0] } = ( split ':', $_ )[1];
}
my $container_regex = ( join "|", keys %containers );
my @containers = (
split /\n/,
run_cmd(
'docker', 'ps', '--no-trunc',
'--filter=' . "name=($container_regex)",
'--format', '{{.Names}}'
)
);
for my $container (@containers) {
my $container_info =
decode_json(
run_cmd(
'docker',
'inspect',
$container
)
)->[0];
my $container_image = ( split /\:/, $container_info->{Image})[1];
my $image_info =
decode_json(
run_cmd(
'docker',
'image',
'inspect',
$container_image
)
)->[0];
croak 'Cannot obtain image info!' if !$image_info;
# we are skipping images that do not have remote digest
next if !$image_info->{RepoDigests}->[0];
my $container_name = ( split /\@/, $image_info->{RepoDigests}->[0] )[0];
# we need array here, because image can be updated without changing tag
# which changes its sha-digest
# if we have older image with the same tag, pull new image and restart
# then RepoDigest will contain multiple images
# smartmatch does the job and is sufficient enough
my @container_sha =
map { ( split /\@/, $_ )[1] } @{ $image_info->{RepoDigests} };
my $url_prefix = 'https://hub.docker.com/v2/repositories/';
my $remote_url = $url_prefix . $container_name . '/tags/?page_size=100';
my $remote_images = send_req($remote_url);
if (!$remote_images) {
$remote_url =
$url_prefix .
'library/' .
$container_name .
'/tags/?page_size=100';
$remote_images = send_req($remote_url);
}
croak 'Cannot obtain remote image info!' if !$remote_images;
my $tag =
( map
{
if ( $container =~ /$_/ ) { $containers{$_} }
else { () }
}
keys %containers
)[0];
$tag //= 'latest';
my $found;
for my $remote_image_info (@{$remote_images}) {
next if $remote_image_info->{name} ne $tag;
$found = '1';
unless ( grep { $remote_image_info->{digest} eq $_ } @container_sha ) {
push @incidents, "$container_name:$tag has updates on DockerHub!";
$exitcode = '2';
}
}
if ( !$found ) {
my ($current_version) = $image_info->{RepoTags}->[0] =~ /:(.+)$/;
my @actual_version = split /\W/, $current_version;
my $is_num = sub { $_[0] =~ /^-?[0-9]+$/ };
my $filter = sub {
my $remote_image = $_[0];
return 0 if grep { $remote_image->{digest} eq $_ } @container_sha;
my @check_version = split /\W/, $remote_image->{name};
my $length
= $#actual_version > $#check_version
? $#actual_version
: $#check_version;
my $cmp;
for my $i ( 0 .. $length ) {
$check_version[$i] //= -1;
$actual_version[$i] //= -1;
return 0
if ( $is_num->( $actual_version[$i] )
!= $is_num->( $check_version[$i] ) );
next
if !$is_num->( $actual_version[$i] )
and
( $actual_version[$i] eq $check_version[$i] or return 0 );
next if $actual_version[$i] == $check_version[$i];
$cmp = $actual_version[$i] < $check_version[$i]
unless defined $cmp;
}
return $cmp;
};
my @versions = grep { $filter->($_) } @{$remote_images};
if (@versions) {
push @incidents,
"New versions found for $container_name:$current_version";
push @incidents, $_->{name} for @versions;
$exitcode = '1';
$found = '1';
}
}
if (!$found) {
push @incidents, "Cannot determine remote digest for $container_name:$tag!";
$exitcode = '2';
}
}
@incidents ? say join( "\n", @incidents ) : say 'OK';
exit $exitcode;
# subs
sub run_cmd {
my @cmd = @_;
my ( $out, $err );
run \@cmd, \undef, \$out, \$err;
chomp $out;
return $out;
}
sub send_req {
my $url = shift;
my $ua = LWP::UserAgent->new();
my $response = $ua->get(
$url, 'Accept' => 'application/json'
);
return if !$response->is_success;
my $content = decode_json( $response->content );
$content->{results} ? return $content->{results} : return $content;
}