add kubernetes restapi plugin

This commit is contained in:
Colin Gagnaire 2019-02-22 17:59:40 +01:00
parent 706779ee09
commit b61565b995
14 changed files with 2180 additions and 0 deletions

View File

@ -0,0 +1,253 @@
#
# Copyright 2019 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::kubernetes::restapi::custom::api;
use strict;
use warnings;
use centreon::plugins::http;
use DateTime;
use JSON::XS;
use URI::Encode;
sub new {
my ($class, %options) = @_;
my $self = {};
bless $self, $class;
if (!defined($options{output})) {
print "Class Custom: Need to specify 'output' argument.\n";
exit 3;
}
if (!defined($options{options})) {
$options{output}->add_option_msg(short_msg => "Class Custom: Need to specify 'options' argument.");
$options{output}->option_exit();
}
if (!defined($options{noptions})) {
$options{options}->add_options(arguments => {
"hostname:s" => { name => 'hostname' },
"url-path:s" => { name => 'url_path' },
"port:s" => { name => 'port' },
"proto:s" => { name => 'proto' },
"token:s" => { name => 'token' },
"proxyurl:s" => { name => 'proxyurl' },
"timeout:s" => { name => 'timeout' },
"ssl-opt:s@" => { name => 'ssl_opt' },
});
}
$options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1);
$self->{output} = $options{output};
$self->{mode} = $options{mode};
$self->{http} = centreon::plugins::http->new(output => $self->{output});
return $self;
}
sub set_options {
my ($self, %options) = @_;
$self->{option_results} = $options{option_results};
}
sub set_defaults {
my ($self, %options) = @_;
foreach (keys %{$options{default}}) {
if ($_ eq $self->{mode}) {
for (my $i = 0; $i < scalar(@{$options{default}->{$_}}); $i++) {
foreach my $opt (keys %{$options{default}->{$_}[$i]}) {
if (!defined($self->{option_results}->{$opt}[$i])) {
$self->{option_results}->{$opt}[$i] = $options{default}->{$_}[$i]->{$opt};
}
}
}
}
}
}
sub check_options {
my ($self, %options) = @_;
$self->{hostname} = (defined($self->{option_results}->{hostname})) ? $self->{option_results}->{hostname} : undef;
$self->{port} = (defined($self->{option_results}->{port})) ? $self->{option_results}->{port} : 443;
$self->{proto} = (defined($self->{option_results}->{proto})) ? $self->{option_results}->{proto} : 'https';
$self->{url_path} = (defined($self->{option_results}->{url_path})) ? $self->{option_results}->{url_path} : '';
$self->{timeout} = (defined($self->{option_results}->{timeout})) ? $self->{option_results}->{timeout} : 10;
$self->{token} = (defined($self->{option_results}->{token})) ? $self->{option_results}->{token} : '';
if (!defined($self->{hostname}) || $self->{hostname} eq '') {
$self->{output}->add_option_msg(short_msg => "Need to specify --hostname option.");
$self->{output}->option_exit();
}
if (!defined($self->{token}) || $self->{token} eq '') {
$self->{output}->add_option_msg(short_msg => "Need to specify --token option.");
$self->{output}->option_exit();
}
return 0;
}
sub build_options_for_httplib {
my ($self, %options) = @_;
$self->{option_results}->{hostname} = $self->{hostname};
$self->{option_results}->{timeout} = $self->{timeout};
$self->{option_results}->{port} = $self->{port};
$self->{option_results}->{proto} = $self->{proto};
$self->{option_results}->{url_path} = $self->{url_path};
$self->{option_results}->{warning_status} = '';
$self->{option_results}->{critical_status} = '';
$self->{option_results}->{unknown_status} = '';
}
sub settings {
my ($self, %options) = @_;
$self->build_options_for_httplib();
$self->{http}->add_header(key => 'Accept', value => 'application/json');
if (defined($self->{access_token})) {
$self->{http}->add_header(key => 'Authorization', value => 'Bearer ' . $self->{access_token});
}
$self->{http}->set_options(%{$self->{option_results}});
}
sub get_connection_info {
my ($self, %options) = @_;
return $self->{hostname} . ":" . $self->{port};
}
sub get_hostname {
my ($self, %options) = @_;
return $self->{hostname};
}
sub get_port {
my ($self, %options) = @_;
return $self->{port};
}
sub get_token {
my ($self, %options) = @_;
return $self->{option_results}->{token};
}
sub request_api {
my ($self, %options) = @_;
if (!defined($self->{access_token})) {
$self->{access_token} = $self->get_token();
}
$self->settings;
$self->{output}->output_add(long_msg => "Query URL: '" . $self->{proto} . "://" . $self->{hostname} .
$self->{url_path} . $options{url_path} . "'", debug => 1);
my $content = $self->{http}->request(url_path => $self->{url_path} . $options{url_path});
my $response = $self->{http}->get_response();
if ($response->code() != 200) {
my $decoded;
eval {
$decoded = JSON::XS->new->utf8->decode($content);
};
if ($@) {
$self->{output}->output_add(long_msg => $content, debug => 1);
$self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@");
$self->{output}->option_exit();
}
if (defined($decoded->{code})) {
$self->{output}->output_add(long_msg => "Error message : " . $decoded->{message}, debug => 1);
$self->{output}->add_option_msg(short_msg => "API return error code '" . $decoded->{code} . "' (add --debug option for detailed message)");
$self->{output}->option_exit();
} else {
$self->{output}->output_add(long_msg => "Error message : " . $decoded, debug => 1);
$self->{output}->add_option_msg(short_msg => "API return error code '" . $response->code() . "' (add --debug option for detailed message)");
$self->{output}->option_exit();
}
}
my $decoded;
eval {
$decoded = JSON::XS->new->utf8->decode($content);
};
if ($@) {
$self->{output}->add_option_msg(short_msg => "Cannot decode json response: $@");
$self->{output}->option_exit();
}
return $decoded;
}
1;
__END__
=head1 NAME
Kubernetes Rest API
=head1 SYNOPSIS
Kubernetes Rest API custom mode
=head1 REST API OPTIONS
Kubernetes Rest API
=over 8
=item B<--hostname>
Kubernetes API hostname.
=item B<--port>
API port (Default: 443)
=item B<--proto>
Specify https if needed (Default: 'https')
=item B<--proxyurl>
Proxy URL if any
=item B<--timeout>
Set HTTP timeout
=item B<--ssl-opt>
Set SSL option (--ssl-opt="SSL_version => TLSv1" --ssl-opt="SSL_verify_mode => SSL_VERIFY_NONE").
=back
=head1 DESCRIPTION
B<custom>.
=cut

View File

@ -0,0 +1,196 @@
#
# Copyright 2019 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::kubernetes::restapi::mode::daemonsetstatus;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold);
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 => '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_output {
my ($self, %options) = @_;
return sprintf("Pods Desired: %s, Current: %s, Available: %s, Up-to-date: %s, Ready: %s, Misscheduled: %s",
$self->{result_values}->{desired},
$self->{result_values}->{current},
$self->{result_values}->{available},
$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}->{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 => '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 => \&catalog_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 => {
"filter-name:s" => { name => 'filter_name' },
"filter-namespace:s" => { name => 'filter_namespace' },
"warning-status:s" => { name => 'warning_status', default => '%{up_to_date} < %{desired}' },
"critical-status:s" => { name => 'critical_status', default => '%{available} < %{desired}' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
$self->change_macros(macros => ['warning_status', 'critical_status']);
}
sub manage_selection {
my ($self, %options) = @_;
$self->{daemonsets} = {};
my $results = $options{custom}->request_api(url_path => '/apis/apps/v1/daemonsets');
foreach my $daemonset (@{$results->{items}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$daemonset->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $daemonset->{metadata}->{name} . "': no matching filter name.", debug => 1);
next;
}
if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' &&
$daemonset->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) {
$self->{output}->output_add(long_msg => "skipping '" . $daemonset->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1);
next;
}
$self->{daemonsets}->{$daemonset->{metadata}->{uid}} = {
display => $daemonset->{metadata}->{name},
namespace => $daemonset->{metadata}->{namespace},
desired => $daemonset->{status}->{desiredNumberScheduled},
current => $daemonset->{status}->{currentNumberScheduled},
up_to_date => $daemonset->{status}->{updatedNumberScheduled},
available => $daemonset->{status}->{numberAvailable},
ready => $daemonset->{status}->{numberReady},
misscheduled => $daemonset->{status}->{numberMisscheduled},
}
}
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<--filter-name>
Filter daemonset name (can be a regexp).
=item B<--filter-namespace>
Filter daemonset namespace (can be a regexp).
=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}
=back
=cut

View File

@ -0,0 +1,207 @@
#
# Copyright 2019 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::kubernetes::restapi::mode::deploymentstatus;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold);
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 => 'ready' . $extra_label,
value => $self->{result_values}->{ready});
$self->{output}->perfdata_add(label => 'up_to_date' . $extra_label,
value => $self->{result_values}->{up_to_date});
}
sub custom_status_output {
my ($self, %options) = @_;
return sprintf("Replicas Desired: %s, Current: %s, Available: %s, Ready: %s, Up-to-date: %s",
$self->{result_values}->{desired},
$self->{result_values}->{current},
$self->{result_values}->{available},
$self->{result_values}->{ready},
$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}->{ready} = $options{new_datas}->{$self->{instance} . '_ready'};
$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 => 'ready' }, { 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 => \&catalog_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 => {
"filter-name:s" => { name => 'filter_name' },
"filter-namespace:s" => { name => 'filter_namespace' },
"warning-status:s" => { name => 'warning_status', default => '%{up_to_date} < %{desired}' },
"critical-status:s" => { name => 'critical_status', default => '%{available} < %{desired}' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
$self->change_macros(macros => ['warning_status', 'critical_status']);
}
sub manage_selection {
my ($self, %options) = @_;
$self->{deployments} = {};
my $results = $options{custom}->request_api(url_path => '/apis/apps/v1/deployments');
foreach my $deployment (@{$results->{items}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$deployment->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $deployment->{metadata}->{name} . "': no matching filter name.", debug => 1);
next;
}
if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' &&
$deployment->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) {
$self->{output}->output_add(long_msg => "skipping '" . $deployment->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1);
next;
}
$self->{deployments}->{$deployment->{metadata}->{uid}} = {
display => $deployment->{metadata}->{name},
namespace => $deployment->{metadata}->{namespace},
desired => $deployment->{spec}->{replicas},
current => $deployment->{status}->{replicas},
ready => $deployment->{status}->{readyReplicas},
up_to_date => $deployment->{status}->{updatedReplicas},
available => $deployment->{status}->{availableReplicas},
}
}
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 PromQL filter, Default: 'deployment=~".*"')
=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)
Example : --metric-overload='metric,^my_metric_name$'
Default :
- 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$
=back
=cut

View File

@ -0,0 +1,128 @@
#
# Copyright 2019 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::kubernetes::restapi::mode::listdaemonsets;
use base qw(centreon::plugins::templates::counter);
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' },
"filter-namespace:s" => { name => 'filter_namespace' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
}
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{custom}->request_api(url_path => '/apis/apps/v1/daemonsets');
foreach my $daemonset (@{$results->{items}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$daemonset->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $daemonset->{metadata}->{name} . "': no matching filter name.", debug => 1);
next;
}
if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' &&
$daemonset->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) {
$self->{output}->output_add(long_msg => "skipping '" . $daemonset->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1);
next;
}
$self->{daemonsets}->{$daemonset->{metadata}->{uid}} = {
uid => $daemonset->{metadata}->{uid},
name => $daemonset->{metadata}->{name},
namespace => $daemonset->{metadata}->{namespace},
}
}
}
sub run {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $daemonset (sort keys %{$self->{daemonsets}}) {
$self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s]",
$self->{daemonsets}->{$daemonset}->{uid},
$self->{daemonsets}->{$daemonset}->{name},
$self->{daemonsets}->{$daemonset}->{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 => ['uid', 'name', 'namespace']);
}
sub disco_show {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $daemonset (sort keys %{$self->{daemonsets}}) {
$self->{output}->add_disco_entry(
uid => $self->{daemonsets}->{$daemonset}->{uid},
name => $self->{daemonsets}->{$daemonset}->{name},
namespace => $self->{daemonsets}->{$daemonset}->{namespace},
);
}
}
1;
__END__
=head1 MODE
List daemonsets.
=over 8
=item B<--filter-name>
Filter daemonset name (can be a regexp).
=item B<--filter-namespace>
Filter daemonset namespace (can be a regexp).
=back
=cut

View File

@ -0,0 +1,128 @@
#
# Copyright 2019 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::kubernetes::restapi::mode::listdeployments;
use base qw(centreon::plugins::templates::counter);
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' },
"filter-namespace:s" => { name => 'filter_namespace' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
}
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{custom}->request_api(url_path => '/apis/apps/v1/deployments');
foreach my $deployment (@{$results->{items}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$deployment->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $deployment->{metadata}->{name} . "': no matching filter name.", debug => 1);
next;
}
if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' &&
$deployment->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) {
$self->{output}->output_add(long_msg => "skipping '" . $deployment->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1);
next;
}
$self->{deployments}->{$deployment->{metadata}->{uid}} = {
uid => $deployment->{metadata}->{uid},
name => $deployment->{metadata}->{name},
namespace => $deployment->{metadata}->{namespace},
}
}
}
sub run {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $deployment (sort keys %{$self->{deployments}}) {
$self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s]",
$self->{deployments}->{$deployment}->{uid},
$self->{deployments}->{$deployment}->{name},
$self->{deployments}->{$deployment}->{namespace}));
}
$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 => ['uid', 'name', 'namespace']);
}
sub disco_show {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $deployment (sort keys %{$self->{deployments}}) {
$self->{output}->add_disco_entry(
uid => $self->{deployments}->{$deployment}->{uid},
name => $self->{deployments}->{$deployment}->{name},
namespace => $self->{deployments}->{$deployment}->{namespace},
);
}
}
1;
__END__
=head1 MODE
List deployments.
=over 8
=item B<--filter-name>
Filter deployment name (can be a regexp).
=item B<--filter-namespace>
Filter deployment namespace (can be a regexp).
=back
=cut

View File

@ -0,0 +1,128 @@
#
# Copyright 2019 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::kubernetes::restapi::mode::listingresses;
use base qw(centreon::plugins::templates::counter);
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' },
"filter-namespace:s" => { name => 'filter_namespace' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
}
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{custom}->request_api(url_path => '/apis/extensions/v1beta1/ingresses');
foreach my $ingress (@{$results->{items}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$ingress->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $ingress->{metadata}->{name} . "': no matching filter name.", debug => 1);
next;
}
if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' &&
$ingress->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) {
$self->{output}->output_add(long_msg => "skipping '" . $ingress->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1);
next;
}
$self->{ingresses}->{$ingress->{metadata}->{uid}} = {
uid => $ingress->{metadata}->{uid},
name => $ingress->{metadata}->{name},
namespace => $ingress->{metadata}->{namespace},
}
}
}
sub run {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $ingress (sort keys %{$self->{ingresses}}) {
$self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s]",
$self->{ingresses}->{$ingress}->{uid},
$self->{ingresses}->{$ingress}->{name},
$self->{ingresses}->{$ingress}->{namespace}));
}
$self->{output}->output_add(severity => 'OK',
short_msg => 'List ingresses:');
$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 => ['uid', 'name', 'namespace']);
}
sub disco_show {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $ingress (sort keys %{$self->{ingresses}}) {
$self->{output}->add_disco_entry(
uid => $self->{ingresses}->{$ingress}->{uid},
name => $self->{ingresses}->{$ingress}->{name},
namespace => $self->{ingresses}->{$ingress}->{namespace},
);
}
}
1;
__END__
=head1 MODE
List ingresses.
=over 8
=item B<--filter-name>
Filter ingress name (can be a regexp).
=item B<--filter-namespace>
Filter ingress namespace (can be a regexp).
=back
=cut

View File

@ -0,0 +1,115 @@
#
# Copyright 2019 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::kubernetes::restapi::mode::listnamespaces;
use base qw(centreon::plugins::templates::counter);
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' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
}
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{custom}->request_api(url_path => '/api/v1/namespaces');
foreach my $namespace (@{$results->{items}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$namespace->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $namespace->{metadata}->{name} . "': no matching filter name.", debug => 1);
next;
}
$self->{namespaces}->{$namespace->{metadata}->{uid}} = {
uid => $namespace->{metadata}->{uid},
name => $namespace->{metadata}->{name},
}
}
}
sub run {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $namespace (sort keys %{$self->{namespaces}}) {
$self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s]",
$self->{namespaces}->{$namespace}->{uid},
$self->{namespaces}->{$namespace}->{name}));
}
$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 => ['uid', 'name']);
}
sub disco_show {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $namespace (sort keys %{$self->{namespaces}}) {
$self->{output}->add_disco_entry(
uid => $self->{namespaces}->{$namespace}->{uid},
name => $self->{namespaces}->{$namespace}->{name},
);
}
}
1;
__END__
=head1 MODE
List namespaces.
=over 8
=item B<--filter-name>
Filter namespace name (can be a regexp).
=back
=cut

View File

@ -0,0 +1,115 @@
#
# Copyright 2019 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::kubernetes::restapi::mode::listnodes;
use base qw(centreon::plugins::templates::counter);
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' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
}
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{custom}->request_api(url_path => '/api/v1/nodes');
foreach my $node (@{$results->{items}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$node->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $node->{metadata}->{name} . "': no matching filter name.", debug => 1);
next;
}
$self->{nodes}->{$node->{metadata}->{uid}} = {
uid => $node->{metadata}->{uid},
name => $node->{metadata}->{name},
}
}
}
sub run {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $node (sort keys %{$self->{nodes}}) {
$self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s]",
$self->{nodes}->{$node}->{uid},
$self->{nodes}->{$node}->{name}));
}
$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 => ['uid', 'name']);
}
sub disco_show {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $node (sort keys %{$self->{nodes}}) {
$self->{output}->add_disco_entry(
uid => $self->{nodes}->{$node}->{uid},
name => $self->{nodes}->{$node}->{name},
);
}
}
1;
__END__
=head1 MODE
List nodes.
=over 8
=item B<--filter-name>
Filter node name (can be a regexp).
=back
=cut

View File

@ -0,0 +1,137 @@
#
# Copyright 2019 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::kubernetes::restapi::mode::listpods;
use base qw(centreon::plugins::templates::counter);
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' },
"filter-namespace:s" => { name => 'filter_namespace' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
}
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{custom}->request_api(url_path => '/api/v1/pods');
foreach my $pod (@{$results->{items}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$pod->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $pod->{metadata}->{name} . "': no matching filter name.", debug => 1);
next;
}
if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' &&
$pod->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) {
$self->{output}->output_add(long_msg => "skipping '" . $pod->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1);
next;
}
$self->{pods}->{$pod->{metadata}->{uid}} = {
uid => $pod->{metadata}->{uid},
name => $pod->{metadata}->{name},
namespace => $pod->{metadata}->{namespace},
node => $pod->{spec}->{nodeName},
status => $pod->{status}->{phase},
ip => $pod->{status}->{podIP},
}
}
}
sub run {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $pod (sort keys %{$self->{pods}}) {
$self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s] [node = %s] [status = %s] [ip = %s]",
$self->{pods}->{$pod}->{uid},
$self->{pods}->{$pod}->{name},
$self->{pods}->{$pod}->{namespace},
$self->{pods}->{$pod}->{node},
$self->{pods}->{$pod}->{status},
$self->{pods}->{$pod}->{ip}));
}
$self->{output}->output_add(severity => 'OK',
short_msg => 'List pods:');
$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 => ['uid', 'name', 'namespace', 'node', 'status', 'ip']);
}
sub disco_show {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $pod (sort keys %{$self->{pods}}) {
$self->{output}->add_disco_entry(
uid => $self->{pods}->{$pod}->{uid},
name => $self->{pods}->{$pod}->{name},
namespace => $self->{pods}->{$pod}->{namespace},
namespace => $self->{pods}->{$pod}->{node},
namespace => $self->{pods}->{$pod}->{status},
namespace => $self->{pods}->{$pod}->{ip},
);
}
}
1;
__END__
=head1 MODE
List pods.
=over 8
=item B<--filter-name>
Filter pod name (can be a regexp).
=item B<--filter-namespace>
Filter pod namespace (can be a regexp).
=back
=cut

View File

@ -0,0 +1,128 @@
#
# Copyright 2019 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::kubernetes::restapi::mode::listreplicasets;
use base qw(centreon::plugins::templates::counter);
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' },
"filter-namespace:s" => { name => 'filter_namespace' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
}
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{custom}->request_api(url_path => '/apis/apps/v1/replicasets');
foreach my $replicaset (@{$results->{items}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$replicaset->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $replicaset->{metadata}->{name} . "': no matching filter name.", debug => 1);
next;
}
if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' &&
$replicaset->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) {
$self->{output}->output_add(long_msg => "skipping '" . $replicaset->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1);
next;
}
$self->{replicasets}->{$replicaset->{metadata}->{uid}} = {
uid => $replicaset->{metadata}->{uid},
name => $replicaset->{metadata}->{name},
namespace => $replicaset->{metadata}->{namespace},
}
}
}
sub run {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $replicaset (sort keys %{$self->{replicasets}}) {
$self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s]",
$self->{replicasets}->{$replicaset}->{uid},
$self->{replicasets}->{$replicaset}->{name},
$self->{replicasets}->{$replicaset}->{namespace}));
}
$self->{output}->output_add(severity => 'OK',
short_msg => 'List replicasets:');
$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 => ['uid', 'name', 'namespace']);
}
sub disco_show {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $replicaset (sort keys %{$self->{replicasets}}) {
$self->{output}->add_disco_entry(
uid => $self->{replicasets}->{$replicaset}->{uid},
name => $self->{replicasets}->{$replicaset}->{name},
namespace => $self->{replicasets}->{$replicaset}->{namespace},
);
}
}
1;
__END__
=head1 MODE
List replicasets.
=over 8
=item B<--filter-name>
Filter replicaset name (can be a regexp).
=item B<--filter-namespace>
Filter replicaset namespace (can be a regexp).
=back
=cut

View File

@ -0,0 +1,128 @@
#
# Copyright 2019 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::kubernetes::restapi::mode::listservices;
use base qw(centreon::plugins::templates::counter);
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' },
"filter-namespace:s" => { name => 'filter_namespace' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
}
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{custom}->request_api(url_path => '/api/v1/services');
foreach my $service (@{$results->{items}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$service->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $service->{metadata}->{name} . "': no matching filter name.", debug => 1);
next;
}
if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' &&
$service->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) {
$self->{output}->output_add(long_msg => "skipping '" . $service->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1);
next;
}
$self->{services}->{$service->{metadata}->{uid}} = {
uid => $service->{metadata}->{uid},
name => $service->{metadata}->{name},
namespace => $service->{metadata}->{namespace},
}
}
}
sub run {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $service (sort keys %{$self->{services}}) {
$self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s]",
$self->{services}->{$service}->{uid},
$self->{services}->{$service}->{name},
$self->{services}->{$service}->{namespace}));
}
$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 => ['uid', 'name', 'namespace']);
}
sub disco_show {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $service (sort keys %{$self->{services}}) {
$self->{output}->add_disco_entry(
uid => $self->{services}->{$service}->{uid},
name => $self->{services}->{$service}->{name},
namespace => $self->{services}->{$service}->{namespace},
);
}
}
1;
__END__
=head1 MODE
List services.
=over 8
=item B<--filter-name>
Filter service name (can be a regexp).
=item B<--filter-namespace>
Filter service namespace (can be a regexp).
=back
=cut

View File

@ -0,0 +1,128 @@
#
# Copyright 2019 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::kubernetes::restapi::mode::liststatefulsets;
use base qw(centreon::plugins::templates::counter);
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' },
"filter-namespace:s" => { name => 'filter_namespace' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
}
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{custom}->request_api(url_path => '/apis/apps/v1/statefulsets');
foreach my $statefulset (@{$results->{items}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$statefulset->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $statefulset->{metadata}->{name} . "': no matching filter name.", debug => 1);
next;
}
if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' &&
$statefulset->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) {
$self->{output}->output_add(long_msg => "skipping '" . $statefulset->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1);
next;
}
$self->{statefulsets}->{$statefulset->{metadata}->{uid}} = {
uid => $statefulset->{metadata}->{uid},
name => $statefulset->{metadata}->{name},
namespace => $statefulset->{metadata}->{namespace},
}
}
}
sub run {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $statefulset (sort keys %{$self->{statefulsets}}) {
$self->{output}->output_add(long_msg => sprintf("[uid = %s] [name = %s] [namespace = %s]",
$self->{statefulsets}->{$statefulset}->{uid},
$self->{statefulsets}->{$statefulset}->{name},
$self->{statefulsets}->{$statefulset}->{namespace}));
}
$self->{output}->output_add(severity => 'OK',
short_msg => 'List statefulsets:');
$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 => ['uid', 'name', 'namespace']);
}
sub disco_show {
my ($self, %options) = @_;
$self->manage_selection(%options);
foreach my $statefulset (sort keys %{$self->{statefulsets}}) {
$self->{output}->add_disco_entry(
uid => $self->{statefulsets}->{$statefulset}->{uid},
name => $self->{statefulsets}->{$statefulset}->{name},
namespace => $self->{statefulsets}->{$statefulset}->{namespace},
);
}
}
1;
__END__
=head1 MODE
List statefulsets.
=over 8
=item B<--filter-name>
Filter statefulset name (can be a regexp).
=item B<--filter-namespace>
Filter statefulset namespace (can be a regexp).
=back
=cut

View File

@ -0,0 +1,323 @@
#
# Copyright 2019 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::kubernetes::restapi::mode::podstatus;
use base qw(centreon::plugins::templates::counter);
use strict;
use warnings;
use centreon::plugins::templates::catalog_functions qw(catalog_status_threshold);
my $instance_mode;
sub custom_pod_status_output {
my ($self, %options) = @_;
return sprintf("Status is '%s'",
$self->{result_values}->{status});
}
sub custom_pod_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'};
return 0;
}
sub custom_container_status_output {
my ($self, %options) = @_;
return sprintf("Status is '%s', State is '%s'",
$self->{result_values}->{status},
$self->{result_values}->{state});
}
sub custom_container_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}->{state} = ($options{new_datas}->{$self->{instance} . '_state'} == 1) ? "ready" : "not ready";
return 0;
}
sub custom_ready_perfdata {
my ($self, %options) = @_;
my $value_perf = $self->{result_values}->{ready};
my $extra_label = '';
$extra_label = '_' . $self->{result_values}->{display} if (!defined($options{extra_instance}) || $options{extra_instance} != 0);
my %total_options = ();
if ($self->{result_values}->{total} > 0 && $instance_mode->{option_results}->{units} eq '%') {
$total_options{total} = $self->{result_values}->{total};
$total_options{cast_int} = 1;
}
$self->{output}->perfdata_add(label => 'containers_ready' . $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 => $total_options{total});
}
sub custom_ready_threshold {
my ($self, %options) = @_;
my ($exit, $threshold_value);
$threshold_value = $self->{result_values}->{ready};
if ($instance_mode->{option_results}->{units} eq '%') {
$threshold_value = $self->{result_values}->{prct_ready};
}
$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_ready_output {
my ($self, %options) = @_;
my $msg = sprintf("Containers Ready: %s/%s (%.2f%%)",
$self->{result_values}->{ready},
$self->{result_values}->{total},
$self->{result_values}->{prct_ready});
return $msg;
}
sub custom_ready_calc {
my ($self, %options) = @_;
$self->{result_values}->{display} = $options{new_datas}->{$self->{instance} . '_display'};
$self->{result_values}->{ready} = $options{new_datas}->{$self->{instance} . '_containers_ready'};
$self->{result_values}->{total} = $options{new_datas}->{$self->{instance} . '_containers_total'};
return 0 if ($self->{result_values}->{total} == 0);
$self->{result_values}->{prct_ready} = $self->{result_values}->{ready} * 100 / $self->{result_values}->{total};
return 0;
}
sub set_counters {
my ($self, %options) = @_;
$self->{maps_counters_type} = [
{ name => 'pods', type => 3, cb_prefix_output => 'prefix_pod_output', cb_long_output => 'long_output',
message_multiple => 'All pods status are ok', indent_long_output => ' ',
group => [
{ name => 'global', type => 0, skipped_code => { -10 => 1 } },
{ name => 'containers', display_long => 1, cb_prefix_output => 'prefix_container_output',
message_multiple => 'All containers status are ok', type => 1, skipped_code => { -10 => 1 } },
]
}
];
$self->{maps_counters}->{global} = [
{ label => 'containers-ready', set => {
key_values => [ { name => 'containers_total' }, { name => 'containers_ready' }, { name => 'display' } ],
closure_custom_calc => $self->can('custom_ready_calc'),
closure_custom_output => $self->can('custom_ready_output'),
closure_custom_perfdata => $self->can('custom_ready_perfdata'),
closure_custom_threshold_check => $self->can('custom_ready_threshold'),
}
},
{ label => 'pod-status', set => {
key_values => [ { name => 'status' } ],
closure_custom_calc => $self->can('custom_pod_status_calc'),
closure_custom_output => $self->can('custom_pod_status_output'),
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&catalog_status_threshold,
}
},
{ label => 'total-restarts-count', set => {
key_values => [ { name => 'restarts_total' }, { name => 'display' } ],
output_template => 'Restarts: %d',
perfdatas => [
{ label => 'restarts_count', value => 'restarts_total_absolute', template => '%d',
min => 0, label_extra_instance => 1, instance_use => 'display_absolute' },
],
}
},
];
$self->{maps_counters}->{containers} = [
{ label => 'container-status', set => {
key_values => [ { name => 'status' }, { name => 'state' } ],
closure_custom_calc => $self->can('custom_container_status_calc'),
closure_custom_output => $self->can('custom_container_status_output'),
closure_custom_perfdata => sub { return 0; },
closure_custom_threshold_check => \&catalog_status_threshold,
}
},
{ label => 'restarts-count', set => {
key_values => [ { name => 'restarts' }, { name => 'perf' } ],
output_template => 'Restarts: %d',
perfdatas => [
{ label => 'restarts_count', value => 'restarts_absolute', template => '%d',
min => 0, label_extra_instance => 1, instance_use => 'perf_absolute' },
],
}
},
];
}
sub prefix_pod_output {
my ($self, %options) = @_;
return "Pod '" . $options{instance_value}->{display} . "' ";
}
sub prefix_container_output {
my ($self, %options) = @_;
return "Container '" . $options{instance_value}->{display} . "' ";
}
sub long_output {
my ($self, %options) = @_;
return "Checking pod '" . $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 => {
"filter-name:s" => { name => 'filter_name' },
"filter-namespace:s" => { name => 'filter_namespace' },
"warning-pod-status:s" => { name => 'warning_pod_status', default => '' },
"critical-pod-status:s" => { name => 'critical_pod_status', default => '%{status} !~ /running/i' },
"warning-container-status:s" => { name => 'warning_container_status', default => '' },
"critical-container-status:s" => { name => 'critical_container_status', default => '%{status} !~ /running/i || %{state} !~ /^ready$/' },
"units:s" => { name => 'units', default => '%' },
});
return $self;
}
sub check_options {
my ($self, %options) = @_;
$self->SUPER::check_options(%options);
$self->change_macros(macros => ['warning_pod_status', 'critical_pod_status',
'warning_container_status', 'critical_container_status']);
$instance_mode = $self;
}
sub manage_selection {
my ($self, %options) = @_;
$self->{pods} = {};
my $results = $options{custom}->request_api(url_path => '/api/v1/pods');
foreach my $pod (@{$results->{items}}) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$pod->{metadata}->{name} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping '" . $pod->{metadata}->{name} . "': no matching filter name.", debug => 1);
next;
}
if (defined($self->{option_results}->{filter_namespace}) && $self->{option_results}->{filter_namespace} ne '' &&
$pod->{metadata}->{namespace} !~ /$self->{option_results}->{filter_namespace}/) {
$self->{output}->output_add(long_msg => "skipping '" . $pod->{metadata}->{namespace} . "': no matching filter namespace.", debug => 1);
next;
}
$self->{pods}->{$pod->{metadata}->{uid}}->{display} = $pod->{metadata}->{name};
$self->{pods}->{$pod->{metadata}->{uid}}->{global} = {
display => $pod->{metadata}->{name},
status => $pod->{status}->{phase},
containers_total => scalar(@{$pod->{status}->{containerStatuses}}),
containers_ready => 0,
restarts_total => 0,
};
foreach my $container (@{$pod->{status}->{containerStatuses}}) {
$self->{pods}->{$pod->{metadata}->{uid}}->{containers}->{$container->{name}} = {
display => $container->{name},
status => keys %{$container->{state}},
state => $container->{ready},
restarts => $container->{restartCount},
perf => $pod->{metadata}->{name} . '_' . $container->{name},
};
$self->{pods}->{$pod->{metadata}->{uid}}->{global}->{containers_ready}++ if ($container->{ready});
$self->{pods}->{$pod->{metadata}->{uid}}->{global}->{restarts_total} += $container->{restartCount};
}
}
if (scalar(keys %{$self->{pods}}) <= 0) {
$self->{output}->add_option_msg(short_msg => "No pods found.");
$self->{output}->option_exit();
}
}
1;
__END__
=head1 MODE
Check pod status.
=over 8
=item B<--warning-pod-status>
Set warning threshold for status (Default: '').
Can used special variables like: %{status}, %{display}
=item B<--critical-pod-status>
Set critical threshold for status (Default: '%{status} !~ /running/i').
Can used special variables like: %{status}, %{display}
=item B<--warning-container-status>
Set warning threshold for status (Default: '').
Can used special variables like: %{status}, %{display}
=item B<--critical-container-status>
Set critical threshold for status (Default: '%{status} !~ /running/i || %{state} !~ /^ready$/').
Can used special variables like: %{status}, %{state}, %{display}
=item B<--warning-*>
Threshold warning.
Can be: 'containers-ready', 'total-restarts-count' (count), 'restarts-count' (count).
=item B<--critical-*>
Threshold critical.
Can be: 'containers-ready', 'total-restarts-count' (count), 'restarts-count' (count).
=item B<--units>
Units of thresholds (Default: '%') ('%', 'count').
=back
=cut

View File

@ -0,0 +1,66 @@
#
# Copyright 2019 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::kubernetes::restapi::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} = '1.0';
%{$self->{modes}} = (
'daemonset-status' => 'cloud::kubernetes::restapi::mode::daemonsetstatus',
'deployment-status' => 'cloud::kubernetes::restapi::mode::deploymentstatus',
'list-daemonsets' => 'cloud::kubernetes::restapi::mode::listdaemonsets',
'list-deployments' => 'cloud::kubernetes::restapi::mode::listdeployments',
'list-ingresses' => 'cloud::kubernetes::restapi::mode::listingresses',
'list-namespaces' => 'cloud::kubernetes::restapi::mode::listnamespaces',
'list-nodes' => 'cloud::kubernetes::restapi::mode::listnodes',
'list-pods' => 'cloud::kubernetes::restapi::mode::listpods',
'list-replicasets' => 'cloud::kubernetes::restapi::mode::listreplicasets',
'list-services' => 'cloud::kubernetes::restapi::mode::listservices',
'list-statefulsets' => 'cloud::kubernetes::restapi::mode::liststatefulsets',
'pod-status' => 'cloud::kubernetes::restapi::mode::podstatus',
);
$self->{custom_modes}{api} = 'cloud::kubernetes::restapi::custom::api';
return $self;
}
sub init {
my ( $self, %options ) = @_;
$self->SUPER::init(%options);
}
1;
__END__
=head1 PLUGIN DESCRIPTION
Check Kubernetes cluster using API.
=cut