����JFIF��x�x����'
Server IP : 78.140.185.180 / Your IP : 18.119.0.207 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 : /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; }