From 9c3548f30f2dabc4055109b349c02aaac3e5aeab Mon Sep 17 00:00:00 2001 From: Simon Bomm Date: Fri, 1 May 2020 18:00:24 +0200 Subject: [PATCH] enh(plugin)add ec2 spot fleet discovery (#1966) Co-authored-by: Thibault S <48209914+thibaults-centreon@users.noreply.github.com> --- cloud/aws/custom/awscli.pm | 29 +++++ cloud/aws/custom/paws.pm | 25 ++++ .../ec2/mode/discoveryspotfleetrequests.pm | 117 ++++++++++++++++++ cloud/aws/ec2/mode/listspotfleetrequests.pm | 96 ++++++++++++++ cloud/aws/ec2/plugin.pm | 24 ++-- 5 files changed, 280 insertions(+), 11 deletions(-) create mode 100644 cloud/aws/ec2/mode/discoveryspotfleetrequests.pm create mode 100644 cloud/aws/ec2/mode/listspotfleetrequests.pm diff --git a/cloud/aws/custom/awscli.pm b/cloud/aws/custom/awscli.pm index 36510b5d2..7c920e8fe 100644 --- a/cloud/aws/custom/awscli.pm +++ b/cloud/aws/custom/awscli.pm @@ -399,6 +399,35 @@ sub ec2spot_get_active_instances_status { return $instance_results; } +sub ec2spot_list_fleet_requests_set_cmd { + my ($self, %options) = @_; + + return if (defined($self->{option_results}->{command_options}) && $self->{option_results}->{command_options} ne ''); + + my $cmd_options = "ec2 describe-spot-fleet-requests --no-dry-run --region $options{region} --output json"; + $cmd_options .= " --endpoint-url $self->{endpoint_url}" if (defined($self->{endpoint_url}) && $self->{endpoint_url} ne ''); + + return $cmd_options; +} + +sub ec2spot_list_fleet_requests { + my ($self, %options) = @_; + + my $cmd_options = $self->ec2spot_list_fleet_requests_set_cmd(%options); + my $raw_results = $self->execute(cmd_options => $cmd_options); + + my $resource_results = []; + foreach my $fleet_request (@{$raw_results->{SpotFleetRequestConfigs}}) { + push @{$resource_results}, { + SpotFleetRequestState => $fleet_request->{SpotFleetRequestState}, + SpotFleetRequestId => $fleet_request->{SpotFleetRequestId}, + ActivityStatus => $fleet_request->{ActivityStatus} + }; + } + + return $resource_results; +} + sub ec2_list_resources_set_cmd { my ($self, %options) = @_; diff --git a/cloud/aws/custom/paws.pm b/cloud/aws/custom/paws.pm index a1cab9d9e..06fcc5f29 100644 --- a/cloud/aws/custom/paws.pm +++ b/cloud/aws/custom/paws.pm @@ -336,6 +336,31 @@ sub ec2spot_get_active_instances { return $instance_results; } +sub ec2spot_list_fleet_requests { + my ($self, %options) = @_; + + my $resource_results = []; + eval { + my $lwp_caller = new Paws::Net::LWPCaller(); + my $ec2spot = Paws->service('EC2', caller => $lwp_caller, region => $options{region}); + my $spot_fleet_requests = $ec2spot->DescribeSpotFleetRequests(DryRun => 0); + + foreach (@{$spot_fleet_requests->{SpotFleetRequestConfigs}}) { + push @{$resource_results}, { + SpotFleetRequestState => $_->{SpotFleetRequestState}, + SpotFleetRequestId => $_->{SpotFleetRequestId}, + ActivityStatus => $_->{ActivityStatus} + }; + } + }; + if ($@) { + $self->{output}->add_option_msg(short_msg => "error: $@"); + $self->{output}->option_exit(); + } + + return $resource_results; +} + sub ec2_list_resources { my ($self, %options) = @_; diff --git a/cloud/aws/ec2/mode/discoveryspotfleetrequests.pm b/cloud/aws/ec2/mode/discoveryspotfleetrequests.pm new file mode 100644 index 000000000..64eeaf6f7 --- /dev/null +++ b/cloud/aws/ec2/mode/discoveryspotfleetrequests.pm @@ -0,0 +1,117 @@ +# +# Copyright 2020 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::aws::ec2::mode::discoveryspotfleetrequests; + +use base qw(centreon::plugins::mode); + +use strict; +use warnings; +use JSON::XS; + +sub new { + my ($class, %options) = @_; + my $self = $class->SUPER::new(package => __PACKAGE__, %options); + bless $self, $class; + + $options{options}->add_options(arguments => { + "prettify" => { name => 'prettify' }, + "filter-state:s" => { name => 'filter_state' }, + }); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub run { + my ($self, %options) = @_; + + my @disco_data; + my $disco_stats; + + $disco_stats->{start_time} = time(); + + my %asgs; + + my $spot_fleet_requests = $options{custom}->discovery( + region => $self->{option_results}->{region}, + service => 'ec2', + command => 'describe-spot-fleet-requests' + + ); + + foreach my $fleet_request (@{$spot_fleet_requests->{SpotFleetRequestConfigs}}) { + my %sfr; + $sfr{state} = $fleet_request->{SpotFleetRequestState}; + $sfr{id} = $fleet_request->{SpotFleetRequestId}; + $sfr{activity_status} = $fleet_request->{ActivityStatus}; + + push @disco_data, \%sfr unless (defined($self->{option_results}->{filter_state}) + && $sfr{state} !~ /$self->{option_results}->{filter_state}/); + } + + $disco_stats->{end_time} = time(); + $disco_stats->{duration} = $disco_stats->{end_time} - $disco_stats->{start_time}; + $disco_stats->{discovered_items} = @disco_data; + $disco_stats->{results} = \@disco_data; + + my $encoded_data; + eval { + if (defined($self->{option_results}->{prettify})) { + $encoded_data = JSON::XS->new->utf8->pretty->encode($disco_stats); + } else { + $encoded_data = JSON::XS->new->utf8->encode($disco_stats); + } + }; + if ($@) { + $encoded_data = '{"code":"encode_error","message":"Cannot encode discovered data into JSON format"}'; + } + + $self->{output}->output_add(short_msg => $encoded_data); + $self->{output}->display(nolabel => 1, force_ignore_perfdata => 1); + $self->{output}->exit(); +} + +1; + +__END__ + +=head1 MODE + +EC2 Spot Fleet Requests discovery. + + +=over 8 + +=item B<--filter-state> + +Filter on Spot Fleet Request state. + +=item B<--prettify> + +Prettify JSON output. + +=back + +=cut diff --git a/cloud/aws/ec2/mode/listspotfleetrequests.pm b/cloud/aws/ec2/mode/listspotfleetrequests.pm new file mode 100644 index 000000000..340dc0bd9 --- /dev/null +++ b/cloud/aws/ec2/mode/listspotfleetrequests.pm @@ -0,0 +1,96 @@ +# +# Copyright 2020 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::aws::ec2::mode::listspotfleetrequests; + +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; + + $options{options}->add_options(arguments => {}); + + return $self; +} + +sub check_options { + my ($self, %options) = @_; + $self->SUPER::init(%options); +} + +sub manage_selection { + my ($self, %options) = @_; + + $self->{spot_fleet_requests} = $options{custom}->ec2spot_list_fleet_requests(region => $self->{option_results}->{region}); +} + +sub run { + my ($self, %options) = @_; + + $self->manage_selection(%options); + foreach (@{$self->{spot_fleet_requests}}) { + $self->{output}->output_add( + long_msg => sprintf("[id = %s][state = %s][status = %s]", + $_->{SpotFleetRequestId}, $_->{SpotFleetRequestState}, $_->{ActivityStatus})); + } + + $self->{output}->output_add(severity => 'OK', + short_msg => 'List spot fleet requests:'); + $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 => ['id', 'state', 'status']); +} + +sub disco_show { + my ($self, %options) = @_; + + $self->manage_selection(%options); + foreach (@{$self->{spot_fleet_requests}}) { + $self->{output}->add_disco_entry( + id => $_->{SpotFleetRequestId}, + state => $_->{SpotFleetRequestState}, + status => $_->{ActivityStatus} + ); + } +} + +1; + +__END__ + +=head1 MODE + +List EC2 Spot Fleet Requests + +=over 8 + +=back + +=cut diff --git a/cloud/aws/ec2/plugin.pm b/cloud/aws/ec2/plugin.pm index a359235ba..42d7cab05 100644 --- a/cloud/aws/ec2/plugin.pm +++ b/cloud/aws/ec2/plugin.pm @@ -31,17 +31,19 @@ sub new { $self->{version} = '0.1'; %{ $self->{modes} } = ( - 'asg-status' => 'cloud::aws::ec2::mode::asgstatus', - 'cpu' => 'cloud::aws::ec2::mode::cpu', - 'discovery' => 'cloud::aws::ec2::mode::discovery', - 'diskio' => 'cloud::aws::ec2::mode::diskio', - 'instances-status' => 'cloud::aws::ec2::mode::instancesstatus', - 'instances-types' => 'cloud::aws::ec2::mode::instancestypes', - 'list-asg' => 'cloud::aws::ec2::mode::listasg', - 'list-instances' => 'cloud::aws::ec2::mode::listinstances', - 'network' => 'cloud::aws::ec2::mode::network', - 'status' => 'cloud::aws::ec2::mode::status', - 'spot-active-instances' => 'cloud::aws::ec2::mode::spotactiveinstances' + 'asg-status' => 'cloud::aws::ec2::mode::asgstatus', + 'cpu' => 'cloud::aws::ec2::mode::cpu', + 'discovery' => 'cloud::aws::ec2::mode::discovery', + 'discovery-fleet-requests' => 'cloud::aws::ec2::mode::discoveryspotfleetrequests', + 'diskio' => 'cloud::aws::ec2::mode::diskio', + 'instances-status' => 'cloud::aws::ec2::mode::instancesstatus', + 'instances-types' => 'cloud::aws::ec2::mode::instancestypes', + 'list-asg' => 'cloud::aws::ec2::mode::listasg', + 'list-instances' => 'cloud::aws::ec2::mode::listinstances', + 'list-spot-fleet-requests' => 'cloud::aws::ec2::mode::listspotfleetrequests', + 'network' => 'cloud::aws::ec2::mode::network', + 'status' => 'cloud::aws::ec2::mode::status', + 'spot-active-instances' => 'cloud::aws::ec2::mode::spotactiveinstances' ); $self->{custom_modes}{paws} = 'cloud::aws::custom::paws';