enh(iplabel): Add new filters to scenarios selection and fix identifiers management

Refs:CTOR-1107
This commit is contained in:
Evan-Adam 2025-01-13 10:41:58 +01:00 committed by GitHub
parent 942c0b7940
commit 47cf7c9e8b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 1219 additions and 120 deletions

View File

@ -43,14 +43,19 @@ sub new {
if (!defined($options{noptions})) {
$options{options}->add_options(arguments => {
'api-username:s' => { name => 'api_username' },
'api-password:s' => { name => 'api_password' },
'hostname:s' => { name => 'hostname' },
'port:s' => { name => 'port' },
'proto:s' => { name => 'proto' },
'timeout:s' => { name => 'timeout' },
'url-path:s' => { name => 'url_path' },
'authent-endpoint' => { name => 'authent_endpoint' }
'api-username:s' => { name => 'api_username' },
'api-password:s' => { name => 'api_password' },
'hostname:s' => { name => 'hostname' },
'port:s' => { name => 'port' },
'proto:s' => { name => 'proto' },
'timeout:s' => { name => 'timeout' },
'url-path:s' => { name => 'url_path' },
'filter-id:s' => { name => 'filter_id' },
'filter-name:s' => { name => 'filter_name' },
'filter-workspaceid:s' => { name => 'filter_workspaceid' },
'filter-siteid:s' => { name => 'filter_siteid' },
'filter-status:s@' => { name => 'filter_status' },
'authent-endpoint' => { name => 'authent_endpoint' }
});
}
$options{options}->add_help(package => __PACKAGE__, sections => 'REST API OPTIONS', once => 1);
@ -170,6 +175,57 @@ sub get_access_token {
return $access_token;
}
sub request_scenarios_status{
my ($self, %options) = @_;
my $status_filter = {};
my @get_param;
if (defined($self->{option_results}->{filter_status}) && $self->{option_results}->{filter_status}[0] ne '') {
$status_filter->{statusFilter} = $self->{option_results}->{filter_status};
}
if (defined($self->{option_results}->{filter_workspaceid}) && $self->{option_results}->{filter_workspaceid} ne '') {
push(@get_param, "workspaceId=$self->{option_results}->{filter_workspaceid}");
}
if (defined($self->{option_results}->{filter_siteid}) && $self->{option_results}->{filter_siteid} ne '') {
push(@get_param, "siteId=$self->{option_results}->{filter_siteid}");
}
my $results = $self->request_api(
endpoint => '/results-api/scenarios/status',
method => 'POST',
post_body => $status_filter,
get_param => \@get_param,
);
if (ref($results) eq "HASH" ) {
if (defined($results->{message})) {
$self->{output}->add_option_msg(short_msg => "Cannot get scenarios : " . $results->{message});
$self->{output}->option_exit();
}
if (defined($results->{error})) {
$self->{output}->add_option_msg(short_msg => "Cannot get scenarios : " . $results->{error});
$self->{output}->option_exit();
}
$self->{output}->add_option_msg(short_msg => "Cannot get scenarios due to an unknown error, please use the --debug option to find more information");
$self->{output}->option_exit();
}
my @scenarios;
for my $scenario (@$results) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$scenario->{scenarioName} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping scenario '" . $scenario->{scenarioName} . "': no matching filter.", debug => 1);
next;
}
if (defined($self->{option_results}->{filter_id}) && $self->{option_results}->{filter_id} ne '' &&
$scenario->{scenarioId} !~ /$self->{option_results}->{filter_id}/) {
$self->{output}->output_add(long_msg => "skipping scenario '" . $scenario->{scenarioName} . "': no matching filter.", debug => 1);
next;
}
push(@scenarios, $scenario);
}
return \@scenarios;
}
sub request_api {
my ($self, %options) = @_;
@ -195,7 +251,7 @@ sub request_api {
$json = JSON::XS->new->utf8->decode($response);
};
if ($@) {
$self->{output}->add_option_msg(short_msg => "Cannot decode Vault JSON response: $@");
$self->{output}->add_option_msg(short_msg => "Cannot decode ekara JSON response: $@");
$self->{output}->option_exit();
};
@ -209,11 +265,11 @@ __END__
=head1 NAME
Ip-Label Ekara Rest API
ip-label Ekara Rest API
=head1 REST API OPTIONS
Ip-Label Ekara Rest API
ip-label Ekara Rest API
=over 8
@ -237,6 +293,37 @@ Set username.
Set password.
=item B<--filter-id>
Filter by monitor ID (can be a regexp).
=item B<--filter-name>
Filter by monitor name (can be a regexp).
=item B<--filter-status>
Filter by numeric status (can be multiple).
0 => 'Unknown',
1 => 'Success',
2 => 'Failure',
3 => 'Aborted',
4 => 'No execution',
5 => 'No execution',
6 => 'Stopped',
7 => 'Excluded',
8 => 'Degraded'
Example: --filter-status='1,2'
=item B<--filter-workspaceid>
Filter scenario to check by workspace id.
=item B<--filter-siteid>
Filter scenario to check by site id.
=item B<--timeout>
Set timeout in seconds (default: 10).

View File

@ -36,6 +36,7 @@ sub custom_status_output {
sub custom_duration_output {
my ($self, %options) = @_;
if ($self->{result_values}->{status} =~ 'Open') {
return sprintf(
'start time: %s, duration: %s',
@ -145,8 +146,6 @@ sub new {
bless $self, $class;
$options{options}->add_options(arguments => {
'filter-id:s' => { name => 'filter_id' },
'filter-name:s' => { name => 'filter_name' },
'ignore-closed' => { name => 'ignore_closed' },
'timeframe:s' => { name => 'timeframe'}
});
@ -176,23 +175,10 @@ my $status_mapping = {
sub manage_selection {
my ($self, %options) = @_;
my $results = $options{custom}->request_api(
endpoint => '/results-api/scenarios/status',
method => 'POST',
);
my $results = $options{custom}->request_scenarios_status();
my $scenarios_list = {};
foreach (@$results) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$_->{scenarioName} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping scenario '" . $_->{scenarioName} . "': no matching filter.", debug => 1);
next;
}
if (defined($self->{option_results}->{filter_id}) && $self->{option_results}->{filter_id} ne '' &&
$_->{scenarioId} !~ /$self->{option_results}->{filter_id}/) {
$self->{output}->output_add(long_msg => "skipping scenario '" . $_->{scenarioName} . "': no matching filter.", debug => 1);
next;
}
push @{$scenarios_list->{scenarioIds}}, $_->{scenarioId};
}
@ -212,6 +198,10 @@ sub manage_selection {
);
}
else{
$self->{output}->add_option_msg(short_msg => "No scenarios found, can't search for incidents. Please check filters.");
$self->{output}->option_exit();
}
$self->{global}->{total} = 0;
@ -257,7 +247,7 @@ __END__
=head1 MODE
Check IP Label Ekara incidents.
Check Ekara incidents.
=over 8
@ -266,14 +256,6 @@ Check IP Label Ekara incidents.
Set timeframe period in seconds. (default: 900)
Example: --timeframe='3600' will check the last hour
=item B<--filter-id>
Filter by monitor ID (can be a regexp).
=item B<--filter-name>
Filter by monitor name (can be a regexp).
=item B<--ignore-closed>
Ignore solved incidents within the timeframe.

View File

@ -34,16 +34,6 @@ sub custom_status_output {
return sprintf('status: %s (%s)', $self->{result_values}->{status}, $self->{result_values}->{num_status});
}
sub custom_date_output {
my ($self, %options) = @_;
return sprintf(
'last execution: %s (%s ago)',
$self->{result_values}->{lastexec},
centreon::plugins::misc::change_seconds(value => $self->{result_values}->{freshness})
);
}
sub prefix_scenario_output {
my ($self, %options) = @_;
@ -131,9 +121,7 @@ sub new {
bless $self, $class;
$options{options}->add_options(arguments => {
'filter-id:s' => { name => 'filter_id' },
'filter-name:s' => { name => 'filter_name' },
'filter-status:s@' => { name => 'filter_status' },
'filter-type:s' => { name => 'filter_type' },
'timeframe:s' => { name => 'timeframe'}
});
@ -162,35 +150,14 @@ my $status_mapping = {
sub manage_selection {
my ($self, %options) = @_;
my $status_filter = {};
if (defined($self->{option_results}->{filter_status}) && $self->{option_results}->{filter_status}[0] ne '') {
$status_filter->{statusFilter} = $self->{option_results}->{filter_status};
}
my $results = $options{custom}->request_api(
endpoint => '/results-api/scenarios/status',
method => 'POST',
post_body => $status_filter
);
my $results = $options{custom}->request_scenarios_status();
my $time = time();
my $start_date = POSIX::strftime('%Y-%m-%dT%H:%M:%SZ', gmtime($time - $self->{timeframe}));
my $end_date = POSIX::strftime('%Y-%m-%dT%H:%M:%SZ', gmtime($time));
foreach (@$results) {
if (defined($self->{option_results}->{filter_name}) && $self->{option_results}->{filter_name} ne '' &&
$_->{scenarioName} !~ /$self->{option_results}->{filter_name}/) {
$self->{output}->output_add(long_msg => "skipping scenario '" . $_->{scenarioName} . "': no matching filter.", debug => 1);
next;
}
if (defined($self->{option_results}->{filter_id}) && $self->{option_results}->{filter_id} ne '' &&
$_->{scenarioId} !~ /$self->{option_results}->{filter_id}/) {
$self->{output}->output_add(long_msg => "skipping scenario '" . $_->{scenarioName} . "': no matching filter.", debug => 1);
next;
}
foreach my $scenario (@$results) {
my $scenario_detail = $options{custom}->request_api(
endpoint => '/results-api/results/' . $_->{scenarioId},
endpoint => '/results-api/results/' . $scenario->{scenarioId},
method => 'POST',
get_param => [
'from=' . $start_date,
@ -200,35 +167,38 @@ sub manage_selection {
if (defined($self->{option_results}->{filter_type}) && $self->{option_results}->{filter_type} ne '' &&
$scenario_detail->{infos}->{plugin_id} !~ /$self->{option_results}->{filter_type}/i) {
$self->{output}->output_add(long_msg => "skipping scenario '" . $_->{scenarioName} . "': no matching filter.", debug => 1);
$self->{output}->output_add(long_msg => "skipping scenario '" . $scenario->{scenarioName} . "': no matching filter.", debug => 1);
next;
}
$self->{scenarios}->{ $_->{scenarioName} } = {
display => $_->{scenarioName},
$self->{scenarios}->{ $scenario->{scenarioName} } = {
display => $scenario->{scenarioName},
global => {
display => $_->{scenarioName},
id => $_->{scenarioId},
num_status => $_->{currentStatus},
status => $status_mapping->{$_->{currentStatus}},
display => $scenario->{scenarioName},
id => $scenario->{scenarioId},
num_status => $scenario->{currentStatus},
status => $status_mapping->{$scenario->{currentStatus}} // 'Unknown',
}
};
foreach my $kpi (@{$scenario_detail->{kpis}}) {
$self->{scenarios}->{ $_->{scenarioName} }->{global}->{$kpi->{label}} = $kpi->{value};
if (!defined $scenario_detail->{results} or scalar(@{$scenario_detail->{results}}) <= 0) {
$self->{output}->add_option_msg(short_msg => "Scenario '" . $scenario->{scenarioName} . "' Don't have any performance data, please try to add a bigger timeframe");
next;
}
$self->{scenarios}->{ $_->{scenarioName} }->{steps_index}->{0} = 'Default';
foreach my $kpi (@{$scenario_detail->{kpis}}) {
$self->{scenarios}->{ $scenario->{scenarioName} }->{global}->{$kpi->{label}} = $kpi->{value};
}
$self->{scenarios}->{ $scenario->{scenarioName} }->{steps_index}->{0} = 'Default';
if ($scenario_detail->{infos}->{info}->{hasStep}) {
foreach my $steps (@{$scenario_detail->{steps}}) {
$self->{scenarios}->{ $_->{scenarioName} }->{steps_index}->{$steps->{index}} = $steps->{name};
$self->{scenarios}->{ $scenario->{scenarioName} }->{steps_index}->{$steps->{index} - 1} = $steps->{name};
}
}
foreach my $step_metrics (@{$scenario_detail->{results}}) {
my $exec_time = str2time($step_metrics->{planningTime}, 'GMT');
$self->{scenarios}->{ $_->{scenarioName} }->{steps}->{ $self->{scenarios}->{ $_->{scenarioName} }->{steps_index}->{ $step_metrics->{stepId} } }->{ $step_metrics->{metric} } = $step_metrics->{value};
$self->{scenarios}->{ $_->{scenarioName} }->{steps}->{ $self->{scenarios}->{ $_->{scenarioName} }->{steps_index}->{ $step_metrics->{stepId} } }->{last_exec} = POSIX::strftime('%d-%m-%Y %H:%M:%S %Z', localtime($exec_time));
$self->{scenarios}->{ $_->{scenarioName} }->{steps}->{ $self->{scenarios}->{ $_->{scenarioName} }->{steps_index}->{ $step_metrics->{stepId} } }->{display} = $self->{scenarios}->{ $_->{scenarioName} }->{steps_index}->{ $step_metrics->{stepId} };
$self->{scenarios}->{ $scenario->{scenarioName} }->{steps}->{ $self->{scenarios}->{ $scenario->{scenarioName} }->{steps_index}->{ $step_metrics->{stepId} } }->{ $step_metrics->{metric} } = $step_metrics->{value};
$self->{scenarios}->{ $scenario->{scenarioName} }->{steps}->{ $self->{scenarios}->{ $scenario->{scenarioName} }->{steps_index}->{ $step_metrics->{stepId} } }->{last_exec} = POSIX::strftime('%d-%m-%Y %H:%M:%S %Z', localtime($exec_time));
$self->{scenarios}->{ $scenario->{scenarioName} }->{steps}->{ $self->{scenarios}->{ $scenario->{scenarioName} }->{steps_index}->{ $step_metrics->{stepId} } }->{display} = $self->{scenarios}->{ $scenario->{scenarioName} }->{steps_index}->{ $step_metrics->{stepId} };
}
}
@ -244,7 +214,7 @@ __END__
=head1 MODE
Check IP Label Ekara scenarios.
Check ip-label Ekara scenarios.
=over 8
@ -253,28 +223,7 @@ Check IP Label Ekara scenarios.
Set timeframe period in seconds. (default: 900)
Example: --timeframe='3600' will check the last hour
=item B<--filter-id>
Filter by monitor ID (can be a regexp).
=item B<--filter-name>
Filter by monitor name (can be a regexp).
=item B<--filter-status>
Filter by numeric status (can be multiple).
0 => 'Unknown',
1 => 'Success',
2 => 'Failure',
3 => 'Aborted',
4 => 'No execution',
5 => 'No execution',
6 => 'Stopped',
7 => 'Excluded',
8 => 'Degraded'
Example: --filter-status='1,2'
=item B<--filter-type>

View File

@ -0,0 +1,36 @@
*** Settings ***
Documentation Check Iplabel incidents
Resource ${CURDIR}${/}..${/}..${/}..${/}..${/}resources/import.resource
Suite Setup Start Mockoon ${MOCKOON_JSON}
Suite Teardown Stop Mockoon
Test Timeout 120s
*** Variables ***
${MOCKOON_JSON} ${CURDIR}${/}monitoring-iplabel-ekara.json
${cmd} ${CENTREON_PLUGINS}
... --plugin=apps::monitoring::iplabel::ekara::restapi::plugin
... --hostname=localhost
... --api-username='username'
... --api-password='password'
... --port='3000'
... --proto='http'
*** Test Cases ***
incidents ${tc}
[Documentation] Check Iplabel scenarios
[Tags] monitoring iplabel restapi
${command} Catenate
... ${cmd}
... --mode=incidents
... ${extra_options}
Ctn Run Command And Check Result As Strings ${command} ${expected_result}
Examples: tc extra_options expected_result --
... 1 --filter-name='Centreon Demo Navigation|AKILA - .Web.' CRITICAL: Incident #25421291, Scenario 'Centreon Demo Navigation' severity: Critical - Incident #25421962, Scenario 'AKILA - (Web)' severity: Critical - Incident #25422458, Scenario 'Centreon Demo Navigation' severity: Critical - Incident #25423513, Scenario 'Centreon Demo Navigation' status: Open, severity: Critical | 'ekara.incidents.current.total.count'=4;;;0;
... 2 --filter-name='not a name' UNKNOWN: No scenarios found, can't search for incidents. Please check filters.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,42 @@
*** Settings ***
Documentation Check Iplabel scenarios
Resource ${CURDIR}${/}..${/}..${/}..${/}..${/}resources/import.resource
Suite Setup Start Mockoon ${MOCKOON_JSON}
Suite Teardown Stop Mockoon
Test Timeout 120s
*** Variables ***
${MOCKOON_JSON} ${CURDIR}${/}monitoring-iplabel-ekara.json
${cmd} ${CENTREON_PLUGINS}
... --plugin=apps::monitoring::iplabel::ekara::restapi::plugin
... --hostname=localhost
... --api-username='username'
... --api-password='password'
... --port='3000'
... --proto='http'
*** Test Cases ***
scenario ${tc}
[Documentation] Check Iplabel scenarios
[Tags] monitoring iplabel restapi
${command} Catenate
... ${cmd}
... --mode=scenarios
... ${extra_options}
Ctn Run Command And Check Result As Strings ${command} ${expected_result}
Examples: tc extra_options expected_result --
... 1 --filter-name='Centreon Demo Navigation|Centreon Demo ping NA' --output-ignore-perfdata CRITICAL: Scenario 'Centreon Demo Navigation': status: Failure (2) WARNING: Scenario 'Centreon Demo ping NA': status: Degraded (8)
... 2 --filter-name='AKILA - Business App' OK: Scenario 'AKILA - Business App': status: Success (1), availability: 100%, time total all steps: 4280ms - All steps are ok | 'AKILA - Business App#scenario.availability.percentage'=100%;;;0;100 'AKILA - Business App#scenario.time.allsteps.total.milliseconds'=4280ms;;;0; 'AKILA - Business App~Dashboard 2#scenario.step.time.milliseconds'=898ms;;;0; 'AKILA - Business App~Dashboard 3#scenario.step.time.milliseconds'=848ms;;;0; 'AKILA - Business App~Run Chrome#scenario.step.time.milliseconds'=2534ms;;;0;
... 3 --filter-name='wrong currentstatus.*' WARNING: Scenario 'wrong currentstatus, no perfdata': status: Unknown (14) - Scenario 'wrong currentstatus, no perfdata' Don't have any performance data, please try to add a bigger timeframe
... 4 --filter-name='not a scenario name' UNKNOWN: No scenario found
... 5 --filter-id='09fe2561.*' --warning-time-total-allsteps='30' --output-ignore-perfdata WARNING: Scenario 'AKILA - (Web) ': time total all steps: 5822ms
... 6 --filter-status='2' --output-ignore-perfdata CRITICAL: Scenario 'Centreon Demo Navigation': status: Failure (2)
... 7 --filter-status='2' --filter-siteid='site' --filter-workspaceid='workspace' --output-ignore-perfdata CRITICAL: Scenario 'Centreon Demo Navigation': status: Failure (2)
... 8 --filter-type='not a scenario type' UNKNOWN: No scenario found
... 9 --api-password='Wrongpassword' --api-username='wrongUsername' UNKNOWN: Authentication endpoint returns error code 'Wrong email or password' (add --debug option for detailed message)

View File

@ -13,8 +13,10 @@ ACS
ADSL
Alcatel
allCapacity
allsteps
Ansible
--api-filter-orgs
api.ip-label.net
api.meraki.com
--api-password
--api-path
@ -31,6 +33,7 @@ AWSCLI
Backbox
base64
blocked-by-uf
BPL
--cacert-file
cardtemperature
centreon
@ -41,14 +44,8 @@ centreonvault
CloudWatch
connections-dhcp
connections-dns
cpu-utilization
cpu-utilization-1m
cpu-utilization-5m
cpu-utilization-5s
CPUs
connections-dhcp
connections-dns
cpu
CPUs
cpu-utilization
cpu-utilization-1m
cpu-utilization-5m
@ -64,11 +61,12 @@ dev
df
--dfsr
dfsrevent
--diskpath
--display-transform-dst
--display-transform-src
--diskpath
dns-resolve-time
--dyn-mode
Ekara
-EncodedCommand
env
ESX
@ -93,6 +91,7 @@ frsevent
HashiCorp
hashicorpvault
HPE
HTTPR
Huawei
ifAlias
ifDesc
@ -110,6 +109,7 @@ InterrupibleSleep
in-ucast
iops
IpAddr
ip-label
ipv4
ipv6
ISAM
@ -178,10 +178,10 @@ NTP
NVOS
--oid
OID
OIDs
--oid-display
--oid-extra-display
--oid-filter
OIDs
okta
oneaccess-sys-mib
OpenMetrics
@ -221,9 +221,9 @@ SkyHigh
SnapMirror
SnapMirrors
SNMP
snmpd.conf
space-usage-prct
--sql-errors-exit
snmpd.conf
SSDCapacity
SSH
statefile