add prometheus kubernetes plugin (#1181)

This commit is contained in:
Colin Gagnaire 2018-10-19 09:54:33 +02:00 committed by GitHub
parent 0d5c0b1da6
commit 06f3a2c486
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 2169 additions and 0 deletions

View File

@ -0,0 +1,267 @@
#
# Copyright 2018 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package cloud::prometheus::direct::kubernetes::mode::containerstatus;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
my $instance_mode;
sub custom_status_threshold {
my ($self, %options) = @_;
my $status = 'ok';
my $message;
eval {
local $SIG{__WARN__} = sub { $message = $_[0]; };
local $SIG{__DIE__} = sub { $message = $_[0]; };
if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' &&
eval "$instance_mode->{option_results}->{critical_status}") {
$status = 'critical';
} elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' &&
eval "$instance_mode->{option_results}->{warning_status}") {
$status = 'warning';
}
};
if (defined($message)) {
$self->{output}->output_add(long_msg => 'filter status issue: ' . $message);
}
return $status;
}
sub custom_status_output {
my ($self, %options) = @_;
my $msg = sprintf("state is '%s', status is '%s'",
$self->{result_values}->{state},
$self->{result_values}->{status});
$msg .= " [reason: " . $self->{result_values}->{reason} . "]" if (defined($self->{result_values}->{reason}) && $self->{result_values}->{reason} ne "");
return $msg;
}
sub custom_status_calc {
my ($self, %options) = @_;
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_container'};
$self->{result_values}->{pod} = $options{new_datas}->{$self->{instance} . '_pod'};
$self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'};
$self->{result_values}->{state} = ($options{new_datas}->{$self->{instance} . '_state'} == 1) ? "ready" : "not ready";
$self->{result_values}->{reason} = $options{new_datas}->{$self->{instance} . '_reason'};
return 0;
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'containers', type => 1, cb_prefix_output => 'prefix_container_output',
message_multiple => 'All containers status are ok', message_separator => ' - ',
skipped_code => { -11 => 1 } },
];
$self->{maps_counters}->{containers} = [
{ label => 'status', set => {
key_values => [ { name => 'status' }, { name => 'state' }, { name => 'reason' }, { name => 'pod' },
{ name => 'container' } ],
closure_custom_calc => $self->can('custom_status_calc'),
closure_custom_output => $self->can('custom_status_output'),
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => $self->can('custom_status_threshold'),
}
},
{ label => 'restarts-count', set => {
key_values => [ { name => 'restarts' }, { name => 'perf' } ],
output_template => 'Restarts count : %d',
perfdatas => [
{ label => 'restarts_count', value => 'restarts_absolute', template => '%d',
min => 0, label_extra_instance => 1, instance_use => 'perf_absolute' },
],
}
},
];
}
sub prefix_container_output {
my ($self, %options) = @_;
return "Container '" . $options{instance_value}->{container} . "' [pod: " . $options{instance_value}->{pod} . "] ";
}
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '1.0';
$options{options}->add_options(arguments =>
{
"container:s" => { name => 'container', default => '.*' },
"pod:s" => { name => 'pod', default => '.*' },
"warning-status:s" => { name => 'warning_status', default => '' },
"critical-status:s" => { name => 'critical_status', default => '%{status} !~ /running/ || %{state} !~ /ready/' },
"extra-filter:s@" => { name => 'extra_filter' },
"metric-overload:s@" => { name => 'metric_overload' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
$self->{metrics} = {
'ready' => '^kube_pod_container_status_ready$',
'running' => '^kube_pod_container_status_running$',
'terminated' => '^kube_pod_container_status_terminated$',
'terminated_reason' => '^kube_pod_container_status_terminated_reason$',
'waiting' => '^kube_pod_container_status_waiting$',
'waiting_reason' => '^kube_pod_container_status_waiting_reason$',
'restarts' => '^kube_pod_container_status_restarts_total$',
};
foreach my $metric (@{$self->{option_results}->{metric_overload}}) {
next if ($metric !~ /(.*),(.*)/);
$self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1}));
}
$instance_mode = $self;
$self->change_macros();
}
sub change_macros {
my ($self, %options) = @_;
foreach (('warning_status', 'critical_status')) {
if (defined($self->{option_results}->{$_})) {
$self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g;
}
}
}
sub manage_selection {
my ($self, %options) = @_;
$self->{containers} = {};
my $extra_filter = '';
foreach my $filter (@{$self->{option_results}->{extra_filter}}) {
$extra_filter .= ',' . $filter;
}
my $results = $options{custom}->query(queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{ready} . '",
container=~"' . $self->{option_results}->{container} . '",
pod=~"' . $self->{option_results}->{pod} .
'"' . $extra_filter . '}, "__name__", "ready", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{running} . '",
container=~"' . $self->{option_results}->{container} . '",
pod=~"' . $self->{option_results}->{pod} .
'"' . $extra_filter . '}, "__name__", "running", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{terminated} . '",
container=~"' . $self->{option_results}->{container} . '",
pod=~"' . $self->{option_results}->{pod} .
'"' . $extra_filter . '}, "__name__", "terminated", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{terminated_reason} . '",
container=~"' . $self->{option_results}->{container} . '",
pod=~"' . $self->{option_results}->{pod} .
'"' . $extra_filter . '}, "__name__", "terminated_reason", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{waiting} . '",
container=~"' . $self->{option_results}->{container} . '",
pod=~"' . $self->{option_results}->{pod} .
'"' . $extra_filter . '}, "__name__", "waiting", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{waiting_reason} . '",
container=~"' . $self->{option_results}->{container} . '",
pod=~"' . $self->{option_results}->{pod} .
'"' . $extra_filter . '}, "__name__", "waiting_reason", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{restarts} . '",
container=~"' . $self->{option_results}->{container} . '",
pod=~"' . $self->{option_results}->{pod} .
'"' . $extra_filter . '}, "__name__", "restarts", "", "")' ]);
foreach my $metric (@{$results}) {
$self->{containers}->{$metric->{metric}->{pod} . "-" . $metric->{metric}->{container}}->{container} = $metric->{metric}->{container};
$self->{containers}->{$metric->{metric}->{pod} . "-" . $metric->{metric}->{container}}->{pod} = $metric->{metric}->{pod};
$self->{containers}->{$metric->{metric}->{pod} . "-" . $metric->{metric}->{container}}->{perf} = $metric->{metric}->{pod} . "_" . $metric->{metric}->{container};
$self->{containers}->{$metric->{metric}->{pod} . "-" . $metric->{metric}->{container}}->{restarts} = ${$metric->{value}}[1] if ($metric->{metric}->{__name__} =~ /restarts/);
$self->{containers}->{$metric->{metric}->{pod} . "-" . $metric->{metric}->{container}}->{state} = ${$metric->{value}}[1] if ($metric->{metric}->{__name__} =~ /ready/);
$self->{containers}->{$metric->{metric}->{pod} . "-" . $metric->{metric}->{container}}->{status} = $metric->{metric}->{__name__} if ($metric->{metric}->{__name__} =~ /running|terminated|waiting/ && ${$metric->{value}}[1] == 1);
$self->{containers}->{$metric->{metric}->{pod} . "-" . $metric->{metric}->{container}}->{reason} = "";
$self->{containers}->{$metric->{metric}->{pod} . "-" . $metric->{metric}->{container}}->{reason} = $metric->{metric}->{reason} if ($metric->{metric}->{__name__} =~ /reason/ && ${$metric->{value}}[1] == 1);
}
if (scalar(keys %{$self->{containers}}) <= 0) {
$self->{output}->add_option_msg(short_msg => "No containers found.");
$self->{output}->option_exit();
}
}
1;
__END__
=head1 MODE
Check container status.
=over 8
=item B<--container>
Filter on a specific container (Must be a regexp, Default: '.*')
=item B<--warning-status>
Set warning threshold for status (Default: '')
Can used special variables like: %{status}, %{state}, %{reason}
=item B<--critical-status>
Set critical threshold for status (Default: '%{status} !~ /running/ || %{state} !~ /ready/').
Can used special variables like: %{status}, %{state}, %{reason}
=item B<--warning-restarts-count>
Threshold warning for container restarts count.
=item B<--critical-restarts-count>
Threshold critical for container restarts count.
=item B<--extra-filter>
Add a PromQL filter (Can be multiple)
Example : --extra-filter='name=~".*pretty.*"'
=item B<--metric-overload>
Overload default metrics name (Can be multiple, metric can be 'status')
Example : --metric-overload='metric,^my_metric_name$'
=back
=cut

View File

@ -0,0 +1,266 @@
#
# Copyright 2018 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package cloud::prometheus::direct::kubernetes::mode::daemonsetstatus;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
my $instance_mode;
sub custom_status_perfdata {
my ($self, %options) = @_;
my $extra_label = '';
if (!defined($options{extra_instance}) || $options{extra_instance} != 0) {
$extra_label .= '_' . $self->{result_values}->{display};
}
$self->{output}->perfdata_add(label => 'desired' . $extra_label,
value => $self->{result_values}->{desired});
$self->{output}->perfdata_add(label => 'current' . $extra_label,
value => $self->{result_values}->{current});
$self->{output}->perfdata_add(label => 'available' . $extra_label,
value => $self->{result_values}->{available});
$self->{output}->perfdata_add(label => 'unavailable' . $extra_label,
value => $self->{result_values}->{unavailable});
$self->{output}->perfdata_add(label => 'up_to_date' . $extra_label,
value => $self->{result_values}->{up_to_date});
$self->{output}->perfdata_add(label => 'ready' . $extra_label,
value => $self->{result_values}->{ready});
$self->{output}->perfdata_add(label => 'misscheduled' . $extra_label,
value => $self->{result_values}->{misscheduled});
}
sub custom_status_threshold {
my ($self, %options) = @_;
my $status = 'ok';
my $message;
eval {
local $SIG{__WARN__} = sub { $message = $_[0]; };
local $SIG{__DIE__} = sub { $message = $_[0]; };
if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' &&
eval "$instance_mode->{option_results}->{critical_status}") {
$status = 'critical';
} elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' &&
eval "$instance_mode->{option_results}->{warning_status}") {
$status = 'warning';
}
};
if (defined($message)) {
$self->{output}->output_add(long_msg => 'filter status issue: ' . $message);
}
return $status;
}
sub custom_status_output {
my ($self, %options) = @_;
return sprintf("nodes desired : %s, current : %s, available : %s, unavailable : %s, up-to-date : %s, ready : %s, misscheduled : %s",
$self->{result_values}->{desired},
$self->{result_values}->{current},
$self->{result_values}->{available},
$self->{result_values}->{unavailable},
$self->{result_values}->{up_to_date},
$self->{result_values}->{ready},
$self->{result_values}->{misscheduled});
}
sub custom_status_calc {
my ($self, %options) = @_;
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'};
$self->{result_values}->{desired} = $options{new_datas}->{$self->{instance} . '_desired'};
$self->{result_values}->{current} = $options{new_datas}->{$self->{instance} . '_current'};
$self->{result_values}->{available} = $options{new_datas}->{$self->{instance} . '_available'};
$self->{result_values}->{unavailable} = $options{new_datas}->{$self->{instance} . '_unavailable'};
$self->{result_values}->{up_to_date} = $options{new_datas}->{$self->{instance} . '_up_to_date'};
$self->{result_values}->{ready} = $options{new_datas}->{$self->{instance} . '_ready'};
$self->{result_values}->{misscheduled} = $options{new_datas}->{$self->{instance} . '_misscheduled'};
return 0;
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'daemonsets', type => 1, cb_prefix_output => 'prefix_daemonset_output', message_multiple => 'All daemonsets status are ok', skipped_code => { -11 => 1 } },
];
$self->{maps_counters}->{daemonsets} = [
{ label => 'status', set => {
key_values => [ { name => 'desired' }, { name => 'current' }, { name => 'up_to_date' },
{ name => 'available' }, { name => 'unavailable' }, { name => 'ready' },
{ name => 'misscheduled' }, { name => 'display' } ],
closure_custom_calc => $self->can('custom_status_calc'),
closure_custom_output => $self->can('custom_status_output'),
closure_custom_perfdata => $self->can('custom_status_perfdata'),
closure_custom_threshold_check => $self->can('custom_status_threshold'),
}
},
];
}
sub prefix_daemonset_output {
my ($self, %options) = @_;
return "Daemonset '" . $options{instance_value}->{display} . "' ";
}
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '1.0';
$options{options}->add_options(arguments =>
{
"daemonset:s" => { name => 'daemonset', default => '.*' },
"warning-status:s" => { name => 'warning_status', default => '%{up_to_date} < %{desired}' },
"critical-status:s" => { name => 'critical_status', default => '%{available} < %{desired}' },
"extra-filter:s@" => { name => 'extra_filter' },
"metric-overload:s@" => { name => 'metric_overload' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
$self->{metrics} = {
'desired' => '^kube_daemonset_status_desired_number_scheduled$',
'current' => '^kube_daemonset_status_current_number_scheduled$',
'available' => '^kube_daemonset_status_number_available$',
'unavailable' => '^kube_daemonset_status_number_unavailable$',
'up_to_date' => '^kube_daemonset_updated_number_scheduled$',
'ready' => '^kube_daemonset_status_number_ready$',
'misscheduled' => '^kube_daemonset_status_number_misscheduled$',
};
foreach my $metric (@{$self->{option_results}->{metric_overload}}) {
next if ($metric !~ /(.*),(.*)/);
$self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1}));
}
$instance_mode = $self;
$self->change_macros();
}
sub change_macros {
my ($self, %options) = @_;
foreach (('warning_status', 'critical_status')) {
if (defined($self->{option_results}->{$_})) {
$self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g;
}
}
}
sub manage_selection {
my ($self, %options) = @_;
$self->{daemonsets} = {};
my $extra_filter = '';
foreach my $filter (@{$self->{option_results}->{extra_filter}}) {
$extra_filter .= ',' . $filter;
}
my $results = $options{custom}->query(queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{desired} . '",
daemonset=~"' . $self->{option_results}->{daemonset} .
'"' . $extra_filter . '}, "__name__", "desired", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{current} . '",
daemonset=~"' . $self->{option_results}->{daemonset} .
'"' . $extra_filter . '}, "__name__", "current", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{available} . '",
daemonset=~"' . $self->{option_results}->{daemonset} .
'"' . $extra_filter . '}, "__name__", "available", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{unavailable} . '",
daemonset=~"' . $self->{option_results}->{daemonset} .
'"' . $extra_filter . '}, "__name__", "unavailable", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{up_to_date} . '",
daemonset=~"' . $self->{option_results}->{daemonset} .
'"' . $extra_filter . '}, "__name__", "up_to_date", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{ready} . '",
daemonset=~"' . $self->{option_results}->{daemonset} .
'"' . $extra_filter . '}, "__name__", "ready", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{misscheduled} . '",
daemonset=~"' . $self->{option_results}->{daemonset} .
'"' . $extra_filter . '}, "__name__", "misscheduled", "", "")' ]);
foreach my $metric (@{$results}) {
$self->{daemonsets}->{$metric->{metric}->{daemonset}}->{display} = $metric->{metric}->{daemonset};
$self->{daemonsets}->{$metric->{metric}->{daemonset}}->{$metric->{metric}->{__name__}} = ${$metric->{value}}[1];
}
if (scalar(keys %{$self->{daemonsets}}) <= 0) {
$self->{output}->add_option_msg(short_msg => "No daemonsets found.");
$self->{output}->option_exit();
}
}
1;
__END__
=head1 MODE
Check daemonset status.
=over 8
=item B<--daemonset>
Filter on a specific daemonset (Must be a regexp, Default: '.*')
=item B<--warning-status>
Set warning threshold for status (Default: '%{up_to_date} < %{desired}')
Can used special variables like: %{display}, %{desired}, %{current},
%{available}, %{unavailable}, %{up_to_date}, %{ready}, %{misscheduled}
=item B<--critical-status>
Set critical threshold for status (Default: '%{available} < %{desired}').
Can used special variables like: %{display}, %{desired}, %{current},
%{available}, %{unavailable}, %{up_to_date}, %{ready}, %{misscheduled}
=item B<--extra-filter>
Add a PromQL filter (Can be multiple)
Example : --extra-filter='name=~".*pretty.*"'
=item B<--metric-overload>
Overload default metrics name (Can be multiple, metric can be 'status')
Example : --metric-overload='metric,^my_metric_name$'
=back
=cut

View File

@ -0,0 +1,249 @@
#
# Copyright 2018 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package cloud::prometheus::direct::kubernetes::mode::deploymentstatus;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
my $instance_mode;
sub custom_status_perfdata {
my ($self, %options) = @_;
my $extra_label = '';
if (!defined($options{extra_instance}) || $options{extra_instance} != 0) {
$extra_label .= '_' . $self->{result_values}->{display};
}
$self->{output}->perfdata_add(label => 'desired' . $extra_label,
value => $self->{result_values}->{desired});
$self->{output}->perfdata_add(label => 'current' . $extra_label,
value => $self->{result_values}->{current});
$self->{output}->perfdata_add(label => 'available' . $extra_label,
value => $self->{result_values}->{available});
$self->{output}->perfdata_add(label => 'unavailable' . $extra_label,
value => $self->{result_values}->{unavailable});
$self->{output}->perfdata_add(label => 'up_to_date' . $extra_label,
value => $self->{result_values}->{up_to_date});
}
sub custom_status_threshold {
my ($self, %options) = @_;
my $status = 'ok';
my $message;
eval {
local $SIG{__WARN__} = sub { $message = $_[0]; };
local $SIG{__DIE__} = sub { $message = $_[0]; };
if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' &&
eval "$instance_mode->{option_results}->{critical_status}") {
$status = 'critical';
} elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' &&
eval "$instance_mode->{option_results}->{warning_status}") {
$status = 'warning';
}
};
if (defined($message)) {
$self->{output}->output_add(long_msg => 'filter status issue: ' . $message);
}
return $status;
}
sub custom_status_output {
my ($self, %options) = @_;
return sprintf("replicas desired : %s, current : %s, available : %s, unavailable : %s, up-to-date : %s",
$self->{result_values}->{desired},
$self->{result_values}->{current},
$self->{result_values}->{available},
$self->{result_values}->{unavailable},
$self->{result_values}->{up_to_date});
}
sub custom_status_calc {
my ($self, %options) = @_;
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'};
$self->{result_values}->{desired} = $options{new_datas}->{$self->{instance} . '_desired'};
$self->{result_values}->{current} = $options{new_datas}->{$self->{instance} . '_current'};
$self->{result_values}->{available} = $options{new_datas}->{$self->{instance} . '_available'};
$self->{result_values}->{unavailable} = $options{new_datas}->{$self->{instance} . '_unavailable'};
$self->{result_values}->{up_to_date} = $options{new_datas}->{$self->{instance} . '_up_to_date'};
return 0;
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'deployments', type => 1, cb_prefix_output => 'prefix_deployment_output', message_multiple => 'All deployments status are ok', skipped_code => { -11 => 1 } },
];
$self->{maps_counters}->{deployments} = [
{ label => 'status', set => {
key_values => [ { name => 'desired' }, { name => 'current' }, { name => 'up_to_date' },
{ name => 'available' }, { name => 'unavailable' }, { name => 'display' } ],
closure_custom_calc => $self->can('custom_status_calc'),
closure_custom_output => $self->can('custom_status_output'),
closure_custom_perfdata => $self->can('custom_status_perfdata'),
closure_custom_threshold_check => $self->can('custom_status_threshold'),
}
},
];
}
sub prefix_deployment_output {
my ($self, %options) = @_;
return "Deployment '" . $options{instance_value}->{display} . "' ";
}
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '1.0';
$options{options}->add_options(arguments =>
{
"deployment:s" => { name => 'deployment', default => '.*' },
"warning-status:s" => { name => 'warning_status', default => '%{up_to_date} < %{desired}' },
"critical-status:s" => { name => 'critical_status', default => '%{available} < %{desired}' },
"extra-filter:s@" => { name => 'extra_filter' },
"metric-overload:s@" => { name => 'metric_overload' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
$self->{metrics} = {
'desired' => '^kube_deployment_spec_replicas$',
'current' => '^kube_deployment_status_replicas$',
'available' => '^kube_deployment_status_replicas_available$',
'unavailable' => '^kube_deployment_status_replicas_unavailable$',
'up_to_date' => '^kube_deployment_status_replicas_updated$',
};
foreach my $metric (@{$self->{option_results}->{metric_overload}}) {
next if ($metric !~ /(.*),(.*)/);
$self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1}));
}
$instance_mode = $self;
$self->change_macros();
}
sub change_macros {
my ($self, %options) = @_;
foreach (('warning_status', 'critical_status')) {
if (defined($self->{option_results}->{$_})) {
$self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g;
}
}
}
sub manage_selection {
my ($self, %options) = @_;
$self->{deployments} = {};
my $extra_filter = '';
foreach my $filter (@{$self->{option_results}->{extra_filter}}) {
$extra_filter .= ',' . $filter;
}
my $results = $options{custom}->query(queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{desired} . '",
deployment=~"' . $self->{option_results}->{deployment} .
'"' . $extra_filter . '}, "__name__", "desired", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{current} . '",
deployment=~"' . $self->{option_results}->{deployment} .
'"' . $extra_filter . '}, "__name__", "current", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{available} . '",
deployment=~"' . $self->{option_results}->{deployment} .
'"' . $extra_filter . '}, "__name__", "available", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{unavailable} . '",
deployment=~"' . $self->{option_results}->{deployment} .
'"' . $extra_filter . '}, "__name__", "unavailable", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{up_to_date} . '",
deployment=~"' . $self->{option_results}->{deployment} .
'"' . $extra_filter . '}, "__name__", "up_to_date", "", "")' ]);
foreach my $metric (@{$results}) {
$self->{deployments}->{$metric->{metric}->{deployment}}->{display} = $metric->{metric}->{deployment};
$self->{deployments}->{$metric->{metric}->{deployment}}->{$metric->{metric}->{__name__}} = ${$metric->{value}}[1];
}
if (scalar(keys %{$self->{deployments}}) <= 0) {
$self->{output}->add_option_msg(short_msg => "No deployments found.");
$self->{output}->option_exit();
}
}
1;
__END__
=head1 MODE
Check deployment status.
=over 8
=item B<--deployment>
Filter on a specific deployment (Must be a regexp, Default: '.*')
=item B<--warning-status>
Set warning threshold for status (Default: '%{up_to_date} < %{desired}')
Can used special variables like: %{display}, %{desired}, %{current},
%{available}, %{unavailable}, %{up_to_date}
=item B<--critical-status>
Set critical threshold for status (Default: '%{available} < %{desired}').
Can used special variables like: %{display}, %{desired}, %{current},
%{available}, %{unavailable}, %{up_to_date}
=item B<--extra-filter>
Add a PromQL filter (Can be multiple)
Example : --extra-filter='name=~".*pretty.*"'
=item B<--metric-overload>
Overload default metrics name (Can be multiple, metric can be 'status')
Example : --metric-overload='metric,^my_metric_name$'
=back
=cut

View File

@ -0,0 +1,134 @@
#
# Copyright 2018 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package cloud::prometheus::direct::kubernetes::mode::listcontainers;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '1.0';
$options{options}->add_options(arguments =>
{
"filter-name:s" => { name => 'filter_name' },
"extra-filter:s@" => { name => 'extra_filter' },
"metric-overload:s@" => { name => 'metric_overload' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
$self->{metrics} = {
'info' => '^kube_pod_container_info$',
};
foreach my $metric (@{$self->{option_results}->{metric_overload}}) {
next if ($metric !~ /(.*),(.*)/);
$self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1}));
}
}
sub manage_selection {
my ($self, %options) = @_;
my $extra_filter = '';
foreach my $filter (@{$self->{option_results}->{extra_filter}}) {
$extra_filter .= ',' . $filter;
}
$self->{containers} = $options{custom}->query(queries => [ '{__name__=~"' . $self->{metrics}->{info} . '"' . $extra_filter . '}' ]);
}
sub run {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $container (@{$self->{containers}}) {
next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne ''
&& $container->{metric}->{container} !~ /$self->{option_results}->{filter_name}/);
$self->{output}->output_add(long_msg => sprintf("[container = %s][container_id = %s][pod = %s][image = %s]",
$container->{metric}->{container}, $container->{metric}->{container_id}, $container->{metric}->{pod},
$container->{metric}->{image}));
}
$self->{output}->output_add(severity => 'OK',
short_msg => 'List containers:');
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
$self->{output}->exit();
}
sub disco_format {
my ($self, %options) = @_;
$self->{output}->add_disco_format(elements => ['container', 'container_id', 'pod', 'image']);
}
sub disco_show {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $container (@{$self->{containers}}) {
$self->{output}->add_disco_entry(
container => $container->{metric}->{container},
container_id => $container->{metric}->{container_id},
pod => $container->{metric}->{pod},
image => $container->{metric}->{image},
);
}
}
1;
__END__
=head1 MODE
List containers.
=over 8
=item B<--filter-name>
Filter container name (Can be a regexp).
=item B<--extra-filter>
Add a PromQL filter (Can be multiple)
Example : --extra-filter='name=~".*pretty.*"'
=item B<--metric-overload>
Overload default metrics name (Can be multiple, metric can be 'labels')
Example : --metric-overload='metric,^my_metric_name$'
=back
=cut

View File

@ -0,0 +1,131 @@
#
# Copyright 2018 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package cloud::prometheus::direct::kubernetes::mode::listdaemonsets;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '1.0';
$options{options}->add_options(arguments =>
{
"filter-name:s" => { name => 'filter_name' },
"extra-filter:s@" => { name => 'extra_filter' },
"metric-overload:s@" => { name => 'metric_overload' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
$self->{metrics} = {
'created' => '^kube_daemonset_created$',
};
foreach my $metric (@{$self->{option_results}->{metric_overload}}) {
next if ($metric !~ /(.*),(.*)/);
$self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1}));
}
}
sub manage_selection {
my ($self, %options) = @_;
my $extra_filter = '';
foreach my $filter (@{$self->{option_results}->{extra_filter}}) {
$extra_filter .= ',' . $filter;
}
$self->{daemonsets} = $options{custom}->query(queries => [ '{__name__=~"' . $self->{metrics}->{created} . '"' . $extra_filter . '}' ]);
}
sub run {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $daemonset (@{$self->{daemonsets}}) {
next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne ''
&& $daemonset->{metric}->{daemonset} !~ /$self->{option_results}->{filter_name}/);
$self->{output}->output_add(long_msg => sprintf("[daemonset = %s][namespace = %s]",
$daemonset->{metric}->{daemonset}, $daemonset->{metric}->{namespace}));
}
$self->{output}->output_add(severity => 'OK',
short_msg => 'List daemonsets:');
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
$self->{output}->exit();
}
sub disco_format {
my ($self, %options) = @_;
$self->{output}->add_disco_format(elements => ['daemonset', 'namespace']);
}
sub disco_show {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $daemonset (@{$self->{daemonsets}}) {
$self->{output}->add_disco_entry(
daemonset => $daemonset->{metric}->{daemonset},
namespace => $daemonset->{metric}->{namespace},
);
}
}
1;
__END__
=head1 MODE
List daemonsets.
=over 8
=item B<--filter-name>
Filter daemonset name (Can be a regexp).
=item B<--extra-filter>
Add a PromQL filter (Can be multiple)
Example : --extra-filter='name=~".*pretty.*"'
=item B<--metric-overload>
Overload default metrics name (Can be multiple, metric can be 'labels')
Example : --metric-overload='metric,^my_metric_name$'
=back
=cut

View File

@ -0,0 +1,129 @@
#
# Copyright 2018 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package cloud::prometheus::direct::kubernetes::mode::listdeployments;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '1.0';
$options{options}->add_options(arguments =>
{
"filter-name:s" => { name => 'filter_name' },
"extra-filter:s@" => { name => 'extra_filter' },
"metric-overload:s@" => { name => 'metric_overload' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
$self->{metrics} = {
'labels' => '^kube_deployment_labels$',
};
foreach my $metric (@{$self->{option_results}->{metric_overload}}) {
next if ($metric !~ /(.*),(.*)/);
$self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1}));
}
}
sub manage_selection {
my ($self, %options) = @_;
my $extra_filter = '';
foreach my $filter (@{$self->{option_results}->{extra_filter}}) {
$extra_filter .= ',' . $filter;
}
$self->{deployments} = $options{custom}->query(queries => [ '{__name__=~"' . $self->{metrics}->{labels} . '"' . $extra_filter . '}' ]);
}
sub run {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $deployment (@{$self->{deployments}}) {
next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne ''
&& $deployment->{metric}->{deployment} !~ /$self->{option_results}->{filter_name}/);
$self->{output}->output_add(long_msg => sprintf("[deployment = %s]", $deployment->{metric}->{deployment}));
}
$self->{output}->output_add(severity => 'OK',
short_msg => 'List deployments:');
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
$self->{output}->exit();
}
sub disco_format {
my ($self, %options) = @_;
$self->{output}->add_disco_format(elements => ['deployment']);
}
sub disco_show {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $deployment (@{$self->{deployments}}) {
$self->{output}->add_disco_entry(
deployment => $deployment->{metric}->{deployment},
);
}
}
1;
__END__
=head1 MODE
List deployments.
=over 8
=item B<--filter-name>
Filter deployment name (Can be a regexp).
=item B<--extra-filter>
Add a PromQL filter (Can be multiple)
Example : --extra-filter='name=~".*pretty.*"'
=item B<--metric-overload>
Overload default metrics name (Can be multiple, metric can be 'labels')
Example : --metric-overload='metric,^my_metric_name$'
=back
=cut

View File

@ -0,0 +1,129 @@
#
# Copyright 2018 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package cloud::prometheus::direct::kubernetes::mode::listnamespaces;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '1.0';
$options{options}->add_options(arguments =>
{
"filter-name:s" => { name => 'filter_name' },
"extra-filter:s@" => { name => 'extra_filter' },
"metric-overload:s@" => { name => 'metric_overload' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
$self->{metrics} = {
'labels' => '^kube_namespace_labels$',
};
foreach my $metric (@{$self->{option_results}->{metric_overload}}) {
next if ($metric !~ /(.*),(.*)/);
$self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1}));
}
}
sub manage_selection {
my ($self, %options) = @_;
my $extra_filter = '';
foreach my $filter (@{$self->{option_results}->{extra_filter}}) {
$extra_filter .= ',' . $filter;
}
$self->{namespaces} = $options{custom}->query(queries => [ '{__name__=~"' . $self->{metrics}->{labels} . '"' . $extra_filter . '}' ]);
}
sub run {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $namespace (@{$self->{namespaces}}) {
next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne ''
&& $namespace->{metric}->{namespace} !~ /$self->{option_results}->{filter_name}/);
$self->{output}->output_add(long_msg => sprintf("[namespace = %s]", $namespace->{metric}->{namespace}));
}
$self->{output}->output_add(severity => 'OK',
short_msg => 'List namespaces:');
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
$self->{output}->exit();
}
sub disco_format {
my ($self, %options) = @_;
$self->{output}->add_disco_format(elements => ['namespace']);
}
sub disco_show {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $namespace (@{$self->{namespaces}}) {
$self->{output}->add_disco_entry(
namespace => $namespace->{metric}->{namespace},
);
}
}
1;
__END__
=head1 MODE
List namespaces.
=over 8
=item B<--filter-name>
Filter namespace name (Can be a regexp).
=item B<--extra-filter>
Add a PromQL filter (Can be multiple)
Example : --extra-filter='name=~".*pretty.*"'
=item B<--metric-overload>
Overload default metrics name (Can be multiple, metric can be 'status')
Example : --metric-overload='metric,^my_metric_name$'
=back
=cut

View File

@ -0,0 +1,138 @@
#
# Copyright 2018 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package cloud::prometheus::direct::kubernetes::mode::listnodes;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '1.0';
$options{options}->add_options(arguments =>
{
"filter-name:s" => { name => 'filter_name' },
"extra-filter:s@" => { name => 'extra_filter' },
"metric-overload:s@" => { name => 'metric_overload' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
$self->{metrics} = {
'info' => '^kube_node_info$',
};
foreach my $metric (@{$self->{option_results}->{metric_overload}}) {
next if ($metric !~ /(.*),(.*)/);
$self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1}));
}
}
sub manage_selection {
my ($self, %options) = @_;
my $extra_filter = '';
foreach my $filter (@{$self->{option_results}->{extra_filter}}) {
$extra_filter .= ',' . $filter;
}
$self->{nodes} = $options{custom}->query(queries => [ '{__name__=~"' . $self->{metrics}->{info} . '"' . $extra_filter . '}' ]);
}
sub run {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $node (@{$self->{nodes}}) {
next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne ''
&& $node->{metric}->{node} !~ /$self->{option_results}->{filter_name}/);
$self->{output}->output_add(long_msg => sprintf("[node = %s][os_image = %s][kubelet_version = %s][kubeproxy_version = %s]" .
"[kernel_version = %s][container_runtime_version = %s]",
$node->{metric}->{node}, $node->{metric}->{os_image}, $node->{metric}->{kubelet_version},
$node->{metric}->{kubeproxy_version}, $node->{metric}->{kernel_version}, $node->{metric}->{container_runtime_version}));
}
$self->{output}->output_add(severity => 'OK',
short_msg => 'List nodes:');
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
$self->{output}->exit();
}
sub disco_format {
my ($self, %options) = @_;
$self->{output}->add_disco_format(elements => ['node', 'os_image', 'kubelet_version', 'kubeproxy_version',
'kernel_version', 'container_runtime_version']);
}
sub disco_show {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $node (@{$self->{nodes}}) {
$self->{output}->add_disco_entry(
node => $node->{metric}->{node},
os_image => $node->{metric}->{os_image},
kubelet_version => $node->{metric}->{kubelet_version},
kubeproxy_version => $node->{metric}->{kubeproxy_version},
kernel_version => $node->{metric}->{kernel_version},
container_runtime_version => $node->{metric}->{container_runtime_version},
);
}
}
1;
__END__
=head1 MODE
List nodes.
=over 8
=item B<--filter-name>
Filter node name (Can be a regexp).
=item B<--extra-filter>
Add a PromQL filter (Can be multiple)
Example : --extra-filter='name=~".*pretty.*"'
=item B<--metric-overload>
Overload default metrics name (Can be multiple, metric can be 'labels')
Example : --metric-overload='metric,^my_metric_name$'
=back
=cut

View File

@ -0,0 +1,131 @@
#
# Copyright 2018 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package cloud::prometheus::direct::kubernetes::mode::listservices;
use base qw(centreon::plugins::mode);
use strict;
use warnings;
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '1.0';
$options{options}->add_options(arguments =>
{
"filter-name:s" => { name => 'filter_name' },
"extra-filter:s@" => { name => 'extra_filter' },
"metric-overload:s@" => { name => 'metric_overload' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::init(%options);
$self->{metrics} = {
'info' => '^kube_service_info$',
};
foreach my $metric (@{$self->{option_results}->{metric_overload}}) {
next if ($metric !~ /(.*),(.*)/);
$self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1}));
}
}
sub manage_selection {
my ($self, %options) = @_;
my $extra_filter = '';
foreach my $filter (@{$self->{option_results}->{extra_filter}}) {
$extra_filter .= ',' . $filter;
}
$self->{services} = $options{custom}->query(queries => [ '{__name__=~"' . $self->{metrics}->{info} . '"' . $extra_filter . '}' ]);
}
sub run {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $service (@{$self->{services}}) {
next if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne ''
&& $service->{metric}->{service} !~ /$self->{option_results}->{filter_name}/);
$self->{output}->output_add(long_msg => sprintf("[service = %s][cluster_ip = %s]",
$service->{metric}->{service}, $service->{metric}->{cluster_ip}));
}
$self->{output}->output_add(severity => 'OK',
short_msg => 'List services:');
$self->{output}->display(nolabel => 1, force_ignore_perfdata => 1, force_long_output => 1);
$self->{output}->exit();
}
sub disco_format {
my ($self, %options) = @_;
$self->{output}->add_disco_format(elements => ['service', 'cluster_ip']);
}
sub disco_show {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $service (@{$self->{services}}) {
$self->{output}->add_disco_entry(
service => $service->{metric}->{service},
cluster_ip => $service->{metric}->{cluster_ip},
);
}
}
1;
__END__
=head1 MODE
List services.
=over 8
=item B<--filter-name>
Filter service name (Can be a regexp).
=item B<--extra-filter>
Add a PromQL filter (Can be multiple)
Example : --extra-filter='name=~".*pretty.*"'
=item B<--metric-overload>
Overload default metrics name (Can be multiple, metric can be 'labels')
Example : --metric-overload='metric,^my_metric_name$'
=back
=cut

View File

@ -0,0 +1,235 @@
#
# Copyright 2018 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package cloud::prometheus::direct::kubernetes::mode::namespacestatus;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
my $instance_mode;
sub custom_status_threshold {
my ($self, %options) = @_;
my $status = 'ok';
my $message;
eval {
local $SIG{__WARN__} = sub { $message = $_[0]; };
local $SIG{__DIE__} = sub { $message = $_[0]; };
if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' &&
eval "$instance_mode->{option_results}->{critical_status}") {
$status = 'critical';
} elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' &&
eval "$instance_mode->{option_results}->{warning_status}") {
$status = 'warning';
}
};
if (defined($message)) {
$self->{output}->output_add(long_msg => 'filter status issue: ' . $message);
}
return $status;
}
sub custom_status_output {
my ($self, %options) = @_;
return sprintf("status phase is '%s'", $self->{result_values}->{phase});
}
sub custom_status_calc {
my ($self, %options) = @_;
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'};
$self->{result_values}->{phase} = $options{new_datas}->{$self->{instance} . '_phase'};
return 0;
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'global', type => 0, cb_init => 'skip_global', cb_prefix_output => 'prefix_global_output' },
{ name => 'namespaces', type => 1, cb_prefix_output => 'prefix_namespace_output', message_multiple => 'All namespaces status are ok', skipped_code => { -11 => 1 } },
];
$self->{maps_counters}->{global} = [
{ label => 'active', set => {
key_values => [ { name => 'active' } ],
output_template => 'Active : %d',
perfdatas => [
{ label => 'active', value => 'active_absolute', template => '%d',
min => 0 },
],
}
},
{ label => 'terminating', set => {
key_values => [ { name => 'terminating' } ],
output_template => 'Terminating : %d',
perfdatas => [
{ label => 'terminating', value => 'terminating_absolute', template => '%d',
min => 0 },
],
}
},
];
$self->{maps_counters}->{namespaces} = [
{ label => 'status', set => {
key_values => [ { name => 'phase' }, { name => 'display' } ],
closure_custom_calc => $self->can('custom_status_calc'),
closure_custom_output => $self->can('custom_status_output'),
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => $self->can('custom_status_threshold'),
}
},
];
}
sub skip_global {
my ($self, %options) = @_;
scalar(keys %{$self->{namespaces}}) > 1 ? return(0) : return(1);
}
sub prefix_global_output {
my ($self, %options) = @_;
return "Namespaces ";
}
sub prefix_namespace_output {
my ($self, %options) = @_;
return "Namespace '" . $options{instance_value}->{display} . "' ";
}
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '1.0';
$options{options}->add_options(arguments =>
{
"namespace:s" => { name => 'namespace', default => '.*' },
"warning-status:s" => { name => 'warning_status' },
"critical-status:s" => { name => 'critical_status', default => '%{phase} !~ /Active/' },
"extra-filter:s@" => { name => 'extra_filter' },
"metric-overload:s@" => { name => 'metric_overload' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
$self->{metrics} = {
'status' => '^kube_namespace_status_phase$',
};
foreach my $metric (@{$self->{option_results}->{metric_overload}}) {
next if ($metric !~ /(.*),(.*)/);
$self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1}));
}
$instance_mode = $self;
$self->change_macros();
}
sub change_macros {
my ($self, %options) = @_;
foreach (('warning_status', 'critical_status')) {
if (defined($self->{option_results}->{$_})) {
$self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g;
}
}
}
sub manage_selection {
my ($self, %options) = @_;
$self->{global} = { active => 0, terminating => 0 };
$self->{namespaces} = {};
my $extra_filter = '';
foreach my $filter (@{$self->{option_results}->{extra_filter}}) {
$extra_filter .= ',' . $filter;
}
my $results = $options{custom}->query(queries => [ '{__name__=~"' . $self->{metrics}->{status} . '",namespace=~"' . $self->{option_results}->{namespace} .
'"' . $extra_filter . '}' ]);
foreach my $metric (@{$results}) {
$self->{namespaces}->{$metric->{metric}->{namespace}}->{display} = $metric->{metric}->{namespace};
$self->{namespaces}->{$metric->{metric}->{namespace}}->{phase} = $metric->{metric}->{phase} if (${$metric->{value}}[1] == 1);
$self->{global}->{lc($metric->{metric}->{phase})}++ if (${$metric->{value}}[1] == 1);
}
if (scalar(keys %{$self->{namespaces}}) <= 0) {
$self->{output}->add_option_msg(short_msg => "No namespaces found.");
$self->{output}->option_exit();
}
}
1;
__END__
=head1 MODE
Check namespace status phase.
=over 8
=item B<--namespace>
Filter on a specific namespace (Must be a regexp, Default: '.*')
=item B<--warning-status>
Set warning threshold for status (Default: '')
Can used special variables like: %{display}, %{phase}.
=item B<--critical-status>
Set critical threshold for status (Default: '%{phase} !~ /Active/').
Can used special variables like: %{display}, %{phase}
=item B<--extra-filter>
Add a PromQL filter (Can be multiple)
Example : --extra-filter='name=~".*pretty.*"'
=item B<--metric-overload>
Overload default metrics name (Can be multiple, metric can be 'status')
Example : --metric-overload='metric,^my_metric_name$'
=back
=cut

View File

@ -0,0 +1,293 @@
#
# Copyright 2018 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package cloud::prometheus::direct::kubernetes::mode::nodestatus;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
my $instance_mode;
sub custom_status_threshold {
my ($self, %options) = @_;
my $status = 'ok';
my $message;
eval {
local $SIG{__WARN__} = sub { $message = $_[0]; };
local $SIG{__DIE__} = sub { $message = $_[0]; };
if (defined($instance_mode->{option_results}->{critical_status}) && $instance_mode->{option_results}->{critical_status} ne '' &&
eval "$instance_mode->{option_results}->{critical_status}") {
$status = 'critical';
} elsif (defined($instance_mode->{option_results}->{warning_status}) && $instance_mode->{option_results}->{warning_status} ne '' &&
eval "$instance_mode->{option_results}->{warning_status}") {
$status = 'warning';
}
};
if (defined($message)) {
$self->{output}->output_add(long_msg => 'filter status issue: ' . $message);
}
return $status;
}
sub custom_status_output {
my ($self, %options) = @_;
return sprintf("status is '%s', new pods schedulable : %s",
$self->{result_values}->{status},
$self->{result_values}->{schedulable});
}
sub custom_status_calc {
my ($self, %options) = @_;
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'};
$self->{result_values}->{status} = $options{new_datas}->{$self->{instance} . '_status'};
$self->{result_values}->{schedulable} = ($options{new_datas}->{$self->{instance} . '_unschedulable'} == 1) ? "false" : "true";
return 0;
}
sub custom_usage_perfdata {
my ($self, %options) = @_;
my $label = 'allocated_pods';
my $value_perf = $self->{result_values}->{allocated};
my $extra_label = '';
$extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0);
my %total_options = ();
if ($instance_mode->{option_results}->{units} eq '%') {
$total_options{total} = $self->{result_values}->{capacity};
$total_options{cast_int} = 1;
}
$self->{output}->perfdata_add(label => $label . $extra_label,
value => $value_perf,
warning => $self->{perfdata}->get_perfdata_for_output(label => 'warning-' . $self->{label}, %total_options),
critical => $self->{perfdata}->get_perfdata_for_output(label => 'critical-' . $self->{label}, %total_options),
min => 0, max => $self->{result_values}->{capacity});
}
sub custom_usage_threshold {
my ($self, %options) = @_;
my ($exit, $threshold_value);
$threshold_value = $self->{result_values}->{allocated};
if ($instance_mode->{option_results}->{units} eq '%') {
$threshold_value = $self->{result_values}->{prct_allocated};
}
$exit = $self->{perfdata}->threshold_check(value => $threshold_value, threshold => [ { label => 'critical-' . $self->{label}, exit_litteral => 'critical' },
{ label => 'warning-'. $self->{label}, exit_litteral => 'warning' } ]);
return $exit;
}
sub custom_usage_output {
my ($self, %options) = @_;
my $msg = sprintf("Allocation Capacity : %s, Allocated : %s (%.2f%%)",
$self->{result_values}->{capacity}, $self->{result_values}->{allocated}, $self->{result_values}->{prct_allocated});
return $msg;
}
sub custom_usage_calc {
my ($self, %options) = @_;
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'};
$self->{result_values}->{capacity} = $options{new_datas}->{$self->{instance} . '_capacity'};
$self->{result_values}->{allocatable} = $options{new_datas}->{$self->{instance} . '_allocatable'};
$self->{result_values}->{allocated} = $self->{result_values}->{capacity} - $self->{result_values}->{allocatable};
$self->{result_values}->{prct_allocated} = ($self->{result_values}->{capacity} > 0) ? $self->{result_values}->{allocated} * 100 / $self->{result_values}->{capacity} : 0;
return 0;
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'nodes', type => 1, cb_prefix_output => 'prefix_node_output', message_multiple => 'All nodes status are ok',
message_separator => ' - ', skipped_code => { -11 => 1 } },
];
$self->{maps_counters}->{nodes} = [
{ label => 'status', set => {
key_values => [ { name => 'status' }, { name => 'unschedulable' }, { name => 'display' } ],
closure_custom_calc => $self->can('custom_status_calc'),
closure_custom_output => $self->can('custom_status_output'),
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => $self->can('custom_status_threshold'),
}
},
{ label => 'allocated-pods', set => {
key_values => [ { name => 'capacity' }, { name => 'allocatable' }, { name => 'display' } ],
closure_custom_calc => $self->can('custom_usage_calc'),
closure_custom_output => $self->can('custom_usage_output'),
closure_custom_perfdata => $self->can('custom_usage_perfdata'),
closure_custom_threshold_check => $self->can('custom_usage_threshold'),
}
},
];
}
sub prefix_node_output {
my ($self, %options) = @_;
return "Node '" . $options{instance_value}->{display} . "' ";
}
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '1.0';
$options{options}->add_options(arguments =>
{
"node:s" => { name => 'node', default => '.*' },
"warning-status:s" => { name => 'warning_status' },
"critical-status:s" => { name => 'critical_status', default => '%{status} !~ /Ready/ || %{schedulable} =~ /false/' },
"extra-filter:s@" => { name => 'extra_filter' },
"metric-overload:s@" => { name => 'metric_overload' },
"units:s" => { name => 'units', default => '' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
$self->{metrics} = {
'status' => '^kube_node_status_condition$',
'unschedulable' => '^kube_node_spec_unschedulable$',
'capacity' => '^kube_node_status_capacity_pods$',
'allocatable' => '^kube_node_status_allocatable_pods$',
};
foreach my $metric (@{$self->{option_results}->{metric_overload}}) {
next if ($metric !~ /(.*),(.*)/);
$self->{metrics}->{$1} = $2 if (defined($self->{metrics}->{$1}));
}
$instance_mode = $self;
$self->change_macros();
}
sub change_macros {
my ($self, %options) = @_;
foreach (('warning_status', 'critical_status')) {
if (defined($self->{option_results}->{$_})) {
$self->{option_results}->{$_} =~ s/%\{(.*?)\}/\$self->{result_values}->{$1}/g;
}
}
}
sub manage_selection {
my ($self, %options) = @_;
$self->{nodes} = {};
my $extra_filter = '';
foreach my $filter (@{$self->{option_results}->{extra_filter}}) {
$extra_filter .= ',' . $filter;
}
my $results = $options{custom}->query(queries => [ 'label_replace({__name__=~"' . $self->{metrics}->{status} . '",
node=~"' . $self->{option_results}->{node} . '",status="true"' .
$extra_filter . '}, "__name__", "status", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{unschedulable} . '",
node=~"' . $self->{option_results}->{node} .
'"' . $extra_filter . '}, "__name__", "unschedulable", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{capacity} . '",
node=~"' . $self->{option_results}->{node} .
'"' . $extra_filter . '}, "__name__", "capacity", "", "")',
'label_replace({__name__=~"' . $self->{metrics}->{allocatable} . '",
node=~"' . $self->{option_results}->{node} .
'"' . $extra_filter . '}, "__name__", "allocatable", "", "")' ]);
foreach my $metric (@{$results}) {
$self->{nodes}->{$metric->{metric}->{node}}->{display} = $metric->{metric}->{node};
$self->{nodes}->{$metric->{metric}->{node}}->{$metric->{metric}->{__name__}} = ${$metric->{value}}[1];
$self->{nodes}->{$metric->{metric}->{node}}->{$metric->{metric}->{__name__}} = $metric->{metric}->{condition} if ($metric->{metric}->{__name__} =~ /status/);
}
if (scalar(keys %{$self->{nodes}}) <= 0) {
$self->{output}->add_option_msg(short_msg => "No nodes found.");
$self->{output}->option_exit();
}
}
1;
__END__
=head1 MODE
Check node status.
=over 8
=item B<--node>
Filter on a specific node (Must be a regexp, Default: '.*')
=item B<--warning-status>
Set warning threshold for status (Default: '')
Can used special variables like: %{display}, %{status}, %{schedulable}
=item B<--critical-status>
Set critical threshold for status (Default: '%{status} !~ /Ready/ || %{schedulable} != /false/').
Can used special variables like: %{display}, %{status}, %{schedulable}
=item B<--warning-allocated-pods>
Threshold warning for pods allocation.
=item B<--critical-allocated-pods>
Threshold critical for pods allocation.
=item B<--units>
Units of thresholds (Default: '') (Can be '%').
=item B<--extra-filter>
Add a PromQL filter (Can be multiple)
Example : --extra-filter='name=~".*pretty.*"'
=item B<--metric-overload>
Overload default metrics name (Can be multiple, metric can be 'status')
Example : --metric-overload='metric,^my_metric_name$'
=back
=cut

View File

@ -0,0 +1,67 @@
#
# Copyright 2018 Centreon (http://www.centreon.com/)
#
# Centreon is a full-fledged industry-strength solution that meets
# the needs in IT infrastructure and application monitoring for
# service performance.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
package cloud::prometheus::direct::kubernetes::plugin;
use strict;
use warnings;
use base qw(centreon::plugins::script_custom);
sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options);
bless $self, $class;
$self->{version} = '0.1';
%{$self->{modes}} = (
'container-status' => 'cloud::prometheus::direct::kubernetes::mode::containerstatus',
'daemonset-status' => 'cloud::prometheus::direct::kubernetes::mode::daemonsetstatus',
'deployment-status' => 'cloud::prometheus::direct::kubernetes::mode::deploymentstatus',
'list-containers' => 'cloud::prometheus::direct::kubernetes::mode::listcontainers',
'list-daemonsets' => 'cloud::prometheus::direct::kubernetes::mode::listdaemonsets',
'list-deployments' => 'cloud::prometheus::direct::kubernetes::mode::listdeployments',
'list-namespaces' => 'cloud::prometheus::direct::kubernetes::mode::listnamespaces',
'list-nodes' => 'cloud::prometheus::direct::kubernetes::mode::listnodes',
'list-services' => 'cloud::prometheus::direct::kubernetes::mode::listservices',
'namespace-status' => 'cloud::prometheus::direct::kubernetes::mode::namespacestatus',
'node-status' => 'cloud::prometheus::direct::kubernetes::mode::nodestatus',
);
$self->{custom_modes}{api} = 'cloud::prometheus::restapi::custom::api';
return $self;
}
sub init {
my ( $self, %options ) = @_;
$self->SUPER::init(%options);
}
1;
__END__
=head1 PLUGIN DESCRIPTION
Check Kubernetes metrics through Prometheus server
using the Kubernetes kube-state-metrics add-on agent.
=cut