fix(http-collection): merge community PR + add tests (#5044)

Co-authored-by: garnier-quentin <qgarnier@ose-consulting.com>
Co-authored-by: qgarnier <garnier.quentin@gmail.com>
Co-authored-by: Colin Gagnaire <gagnaire.colin@gmail.com>
Co-authored-by: pkippes <pkippes@centreon.com>
Co-authored-by: tuntoja <58987095+tuntoja@users.noreply.github.com>
Co-authored-by: May <110405507+paul-oureib@users.noreply.github.com>
This commit is contained in:
omercier 2024-06-03 11:22:38 +02:00 committed by GitHub
parent 2d00dc5bbe
commit 72d46d1cb5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 736 additions and 49 deletions

View File

@ -1,7 +1,9 @@
{
"dependencies": [
"libjson-maybexs-perl",
"libjson-perl",
"libxml-xpath-perl",
"libxml-libxml-perl",
"libxml-libxml-simple-perl"
]
}

View File

@ -87,7 +87,7 @@ sub custom_select_output {
if (defined($format)) {
return sprintf(
$format->{printf_msg}, @{$format->{printf_var}}
$format->{printf_msg}, @{$format->{printf_var}}
);
}
@ -123,7 +123,7 @@ sub new {
my ($class, %options) = @_;
my $self = $class->SUPER::new(package => __PACKAGE__, %options, force_new_perfdata => 1);
bless $self, $class;
$options{options}->add_options(arguments => {
'config:s' => { name => 'config' },
'filter-selection:s%' => { name => 'filter_selection' },
@ -192,7 +192,7 @@ sub get_map_value {
my ($self, %options) = @_;
return undef if (
!defined($self->{config}->{mapping}) ||
!defined($self->{config}->{mapping}) ||
!defined($self->{config}->{mapping}->{ $options{map} })
);
return '' if (!defined($self->{config}->{mapping}->{ $options{map} }->{ $options{value} }));
@ -254,8 +254,9 @@ sub get_payload {
sub call_http {
my ($self, %options) = @_;
if (!defined($options{rq}->{hostname}) || $options{rq}->{hostname} eq '') {
$self->{output}->add_option_msg(short_msg => "hostname attribute is missing [http > requests > $options{rq}->{name}]");
if ((!defined($options{rq}->{full_url}) || $options{rq}->{full_url} eq '') &&
(!defined($options{rq}->{hostname}) || $options{rq}->{hostname} eq '')) {
$self->{output}->add_option_msg(short_msg => "hostname or full_url attribute is missing [http > requests > $options{rq}->{name}]");
$self->{output}->option_exit();
}
if (!defined($options{rq}->{rtype}) || $options{rq}->{rtype} !~ /^(?:txt|json|xml)$/) {
@ -298,11 +299,19 @@ sub call_http {
$http = centreon::plugins::http->new(noptions => 1, output => $self->{output});
}
my $full_url;
my $hostname = $self->substitute_string(value => $options{rq}->{hostname});
if (defined($options{rq}->{full_url}) && $options{rq}->{full_url} ne '') {
$full_url = $self->substitute_string(value => $options{rq}->{full_url});
$hostname = '';
}
my $timing0 = [gettimeofday];
my ($content) = $http->request(
backend => $self->substitute_string(value => $options{rq}->{backend}),
http_backend => $self->substitute_string(value => $options{rq}->{backend}),
method => $self->substitute_string(value => $options{rq}->{method}),
hostname => $self->substitute_string(value => $options{rq}->{hostname}),
full_url => $full_url,
hostname => $hostname,
proto => $self->substitute_string(value => $options{rq}->{proto}),
port => $self->substitute_string(value => $options{rq}->{port}),
url_path => $self->substitute_string(value => $options{rq}->{endpoint}),
@ -321,26 +330,6 @@ sub call_http {
$self->add_builtin(name => 'httpCode.' . $options{rq}->{name}, value => $http->get_code());
$self->add_builtin(name => 'httpMessage.' . $options{rq}->{name}, value => $http->get_message());
if ($options{rq}->{rtype} eq 'json') {
eval {
$content = JSON::XS->new->utf8->decode($content);
};
} elsif ($options{rq}->{rtype} eq 'xml') {
eval {
$SIG{__WARN__} = sub {};
$content = XMLin($content, ForceArray => $options{rq}->{force_array}, KeyAttr => []);
};
}
if ($@) {
$self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)");
$self->{output}->output_add(long_msg => "$@", debug => 1);
$self->{output}->option_exit();
}
my $encoded = JSON::XS->new->utf8->pretty->encode($content);
$self->{output}->output_add(long_msg => '======> returned JSON structure:', debug => 1);
$self->{output}->output_add(long_msg => "$encoded", debug => 1);
return ($http->get_header(), $content, $http);
}
@ -441,8 +430,31 @@ sub parse_structure {
$options{conf}->{path} = $self->substitute_string(value => $options{conf}->{path});
my $content;
if ($options{rtype} eq 'json') {
eval {
$content = JSON::XS->new->utf8->decode($options{content});
};
} elsif ($options{rtype} eq 'xml') {
eval {
$SIG{__WARN__} = sub {};
$content = XMLin($options{content}, ForceArray => $options{force_array}, KeyAttr => []);
};
}
if ($@) {
$self->{output}->add_option_msg(short_msg => "Cannot decode response (add --debug option to display returned content)");
$self->{output}->output_add(long_msg => "$@", debug => 1);
$self->{output}->option_exit();
}
if ($self->{output}->is_debug()) {
my $encoded = JSON::XS->new->allow_nonref(1)->utf8->pretty->encode($content);
$self->{output}->output_add(long_msg => '======> returned JSON structure:', debug => 1);
$self->{output}->output_add(long_msg => "$encoded", debug => 1);
}
my $jpath = JSON::Path->new($options{conf}->{path});
my @values = $jpath->values($options{content});
my @values = $jpath->values($content);
my $local = {};
my $i = 0;
@ -534,26 +546,50 @@ sub collect_http_tables {
($headers, $content, $http) = $self->call_http(rq => $options{requests}->[$i], http => $options{http});
$self->set_builtin();
next if (!defined($options{requests}->[$i]->{parse}));
my $local;
foreach my $conf (@{$options{requests}->[$i]->{parse}}) {
if ($options{requests}->[$i]->{rtype} eq 'txt') {
$local = $self->parse_txt(name => $options{requests}->[$i]->{name}, headers => $headers, content => $content, conf => $conf);
} else {
$local = $self->parse_structure(name => $options{requests}->[$i]->{name}, content => $content, conf => $conf);
}
}
if (defined($options{requests}->[$i]->{scenario_stopped}) && $options{requests}->[$i]->{scenario_stopped} &&
$self->check_filter2(filter => $options{requests}->[$i]->{scenario_stopped}, values => $self->{expand})) {
if (defined($options{requests}->[$i]->{scenario_stopped_first}) && $options{requests}->[$i]->{scenario_stopped_first} &&
$self->check_filter2(filter => $options{requests}->[$i]->{scenario_stopped_first}, values => $self->{expand})) {
$self->{scenario_stopped} = 1;
if (defined($options{requests}->[$i]->{scenario_retry}) && $options{requests}->[$i]->{scenario_retry} =~ /^true|1$/i) {
$self->{scenario_loop}++;
$self->{scenario_retry} = 1;
}
} else {
$self->save_local_http_cache(local_http_cache => $local_http_cache, local => $local);
my $local = {};
if (defined($options{requests}->[$i]->{parse})) {
foreach my $conf (@{$options{requests}->[$i]->{parse}}) {
my $lentries = {};
if ($options{requests}->[$i]->{rtype} eq 'txt') {
$lentries = $self->parse_txt(name => $options{requests}->[$i]->{name}, headers => $headers, content => $content, conf => $conf);
} else {
$lentries = $self->parse_structure(
name => $options{requests}->[$i]->{name},
content => $content,
conf => $conf,
rtype => $options{requests}->[$i]->{rtype},
force_array => $options{requests}->[$i]->{force_array}
);
}
$local = { %$local, %$lentries };
}
}
$self->set_functions(
section => "http > requests > $options{requests}->[$i]->{name}",
functions => $options{requests}->[$i]->{functions},
default => 1
);
if (defined($options{requests}->[$i]->{scenario_stopped}) && $options{requests}->[$i]->{scenario_stopped} &&
$self->check_filter2(filter => $options{requests}->[$i]->{scenario_stopped}, values => $self->{expand})) {
$self->{scenario_stopped} = 1;
if (defined($options{requests}->[$i]->{scenario_retry}) && $options{requests}->[$i]->{scenario_retry} =~ /^true|1$/i) {
$self->{scenario_loop}++;
$self->{scenario_retry} = 1;
}
} else {
$self->save_local_http_cache(local_http_cache => $local_http_cache, local => $local);
}
}
}
@ -625,6 +661,16 @@ sub use_local_http_cache {
}
}
my $builtin = $local_http_cache->get(name => 'builtin');
foreach my $name (keys %$builtin) {
$self->add_builtin(name => $name, value => $builtin->{$name});
}
my $local_vars = $local_http_cache->get(name => 'local_vars');
foreach my $name (keys %$local_vars) {
$self->set_local_variable(name => $name, value => $local_vars->{$name});
}
return 1;
}
@ -632,12 +678,20 @@ sub save_local_http_cache {
my ($self, %options) = @_;
if (defined($options{local_http_cache})) {
my $expand = {};
foreach my $name (keys %{$self->{expand}}) {
next if ($name =~ /^(builtin|constants)\./);
$expand->{$name} = $self->{expand}->{$name};
}
$options{local_http_cache}->write(
data => {
http_collected => {
tables => $options{local},
epoch => time()
}
},
builtin => $self->{builtin},
local_vars => $expand
}
);
}
@ -737,6 +791,17 @@ sub display_variables {
}
}
}
foreach my $name (keys %{$self->{expand}}) {
$self->{output}->output_add(
long_msg => sprintf(
' %s = %s',
$name,
$self->{expand}->{$name}
),
debug => 1
);
}
}
sub collect_http {
@ -765,6 +830,13 @@ sub collect_http {
$self->collect_http_sampling();
# can use local_var set for selection/selection_loop
$self->{local_vars} = {};
foreach my $name (keys %{$self->{expand}}) {
next if ($name =~ /^(builtin|constants)\./);
$self->{local_vars}->{$name} = $self->{expand}->{$name};
}
if ($self->{output}->is_debug()) {
$self->display_variables();
}
@ -790,6 +862,14 @@ sub get_local_variable {
}
sub set_local_variables {
my ($self, %options) = @_;
foreach (keys %{$self->{local_vars}}) {
$self->set_local_variable(name => $_, value => $self->{local_vars}->{$_});
}
}
sub set_local_variable {
my ($self, %options) = @_;
@ -934,7 +1014,7 @@ sub parse_http_tables {
($code, $msg_error, $end, $table_label) = $self->parse_forward(
chars => $options{chars},
start => $options{start},
allowed => '[a-zA-Z0-9_]',
allowed => '[a-zA-Z0-9_\-]',
stop => '[).]'
);
if ($code) {
@ -999,7 +1079,7 @@ sub parse_http_tables {
($code, $msg_error, $end, $label) = $self->parse_forward(
chars => $options{chars},
start => $end + 2,
allowed => '[a-zA-Z0-9_]',
allowed => '[a-zA-Z0-9_\-]',
stop => '[)]'
);
if ($code) {
@ -1039,7 +1119,7 @@ sub parse_special_variable {
my ($code, $msg_error, $end, $label) = $self->parse_forward(
chars => $options{chars},
start => $start + 2,
allowed => '[a-zA-Z0-9\._]',
allowed => '[a-zA-Z0-9\._\-]',
stop => '[)]'
);
if ($code) {
@ -1630,6 +1710,7 @@ sub exec_func_capture {
$self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed in save attribute");
$self->{output}->option_exit();
}
$self->set_special_variable_value(value => $value, %$save);
}
}
@ -1707,7 +1788,7 @@ sub prepare_variables {
return undef if (!defined($options{value}));
while ($options{value} =~ /%\(([a-zA-Z0-9\.]+?)\)/g) {
while ($options{value} =~ /%\(([a-zA-Z0-9\.\-]+?)\)/g) {
next if ($1 =~ /^http\./);
$options{value} =~ s/%\(($1)\)/\$expand->{'$1'}/g;
}
@ -1721,7 +1802,7 @@ sub check_filter {
return 0 if (!defined($options{filter}) || $options{filter} eq '');
our $expand = $options{values};
$options{filter} =~ s/%\(([a-zA-Z0-9\._:]+?)\)/\$expand->{'$1'}/g;
$options{filter} =~ s/%\(([a-zA-Z0-9\._:\-]+?)\)/\$expand->{'$1'}/g;
my $result = $self->{safe}->reval("$options{filter}");
if ($@) {
$self->{output}->add_option_msg(short_msg => 'Unsafe code evaluation: ' . $@);
@ -1737,7 +1818,7 @@ sub check_filter2 {
return 0 if (!defined($options{filter}) || $options{filter} eq '');
our $expand = $options{values};
$options{filter} =~ s/%\(([a-zA-Z0-9\._:]+?)\)/\$expand->{'$1'}/g;
$options{filter} =~ s/%\(([a-zA-Z0-9\._:\-]+?)\)/\$expand->{'$1'}/g;
my $result = $self->{safe}->reval("$options{filter}");
if ($@) {
$self->{output}->add_option_msg(short_msg => 'Unsafe code evaluation: ' . $@);
@ -1820,6 +1901,7 @@ sub add_selection {
my $config = {};
$self->{expand} = $self->set_constants();
$self->set_builtin();
$self->set_local_variables();
$self->{expand}->{name} = $_->{name} if (defined($_->{name}));
$self->set_functions(section => "selection > $i > functions", functions => $_->{functions}, position => 'before_expand');
$self->set_expand_table(section => "selection > $i > expand_table", expand => $_->{expand_table});
@ -1857,20 +1939,26 @@ sub add_selection_loop {
next if (!defined($_->{source}) || $_->{source} eq '');
$self->{current_section} = '[selection_loop > ' . $i . ' > source]';
my $result = $self->parse_special_variable(chars => [split //, $_->{source}], start => 0);
if ($result->{type} != 2) {
$self->{output}->add_option_msg(short_msg => $self->{current_section} . " special variable type not allowed");
$self->{output}->option_exit();
}
next if (!defined($self->{http_collected}->{tables}->{ $result->{table} }));
foreach my $instance (keys %{$self->{http_collected}->{tables}->{ $result->{table} }}) {
$self->{expand} = $self->set_constants();
$self->set_builtin();
$self->set_local_variables();
$self->{expand}->{ $result->{table} . '.instance' } = $instance;
foreach my $label (keys %{$self->{http_collected}->{tables}->{ $result->{table} }->{$instance}}) {
$self->{expand}->{ $result->{table} . '.' . $label } =
$self->{http_collected}->{tables}->{ $result->{table} }->{$instance}->{$label};
}
my $config = {};
$self->{expand}->{name} = $_->{name} if (defined($_->{name}));
$self->set_functions(section => "selection_loop > $i > functions", functions => $_->{functions}, position => 'before_expand');

View File

@ -0,0 +1,61 @@
{
"constants": {
"protocol": "https",
"port": "443",
"customPath": "centreon"
},
"http": {
"requests": [
{
"name": "authenticationRequest",
"hostname": "%(constants.hostname)",
"proto": "%(constants.protocol)",
"port": "%(constants.port)",
"endpoint": "/%(constants.customPath)/api/latest/login",
"method": "POST",
"headers": [
"Accept:application/json",
"Content-Type:application/json"
],
"timeout": 30,
"payload": {
"type": "json",
"value": {
"security": {
"credentials": {
"login": "%(constants.username)",
"password": "%(constants.password)"
}
}
}
},
"backend": "curl",
"rtype": "json",
"parse": [
{
"name": "token",
"path": "$.security.token",
"entries": [
{
"id": "value"
}
]
}
]
}
]
},
"selection": [
{
"name": "authenticationSelection",
"critical": "defined(%(builtin.httpCode.authenticationRequest)) and %(builtin.httpCode.authenticationRequest) != 200",
"formatting": {
"printf_msg": "Authentication resulted in %s HTTP code",
"printf_var": [
"%(builtin.httpCode.authenticationRequest)"
],
"display_ok": true
}
}
]
}

View File

@ -0,0 +1,160 @@
{
"constants": {
"protocol": "https",
"port": "443",
"customPath": "centreon"
},
"http": {
"requests": [
{
"name": "authenticationRequest",
"hostname": "%(constants.hostname)",
"proto": "%(constants.protocol)",
"port": "%(constants.port)",
"endpoint": "/%(constants.customPath)/api/latest/login",
"method": "POST",
"headers": [
"Accept:application/json",
"Content-Type:application/json"
],
"timeout": 30,
"payload": {
"type": "json",
"value": {
"security": {
"credentials": {
"login": "%(constants.username)",
"password": "%(constants.password)"
}
}
}
},
"scenario_stopped": "%(builtin.httpCode.authenticationRequest) != 200",
"backend": "curl",
"rtype": "json",
"parse": [
{
"name": "token",
"path": "$.security.token",
"entries": [
{
"id": "value"
}
]
}
]
},
{
"name": "resourcesRequest",
"hostname": "%(constants.hostname)",
"proto": "%(constants.protocol)",
"port": "%(constants.port)",
"endpoint": "/%(constants.customPath)/api/latest/monitoring/resources?limit=1000&search={\"information\": {\"$eq\": \"(Execute command failed)\"}}",
"method": "GET",
"headers": [
"X-AUTH-TOKEN: %(http.tables.authenticationRequestToken.[0].value)",
"Accept: text/json"
],
"timeout": 30,
"scenario_stopped": "%(builtin.httpCode.authenticationRequest) != 200",
"backend": "curl",
"rtype": "json",
"parse": [
{
"name": "meta",
"type": "body",
"path": "$.meta",
"entries": [
{
"id": "total"
}
]
},
{
"name": "entries",
"type": "body",
"path": "$.result[*]",
"entries": [
{
"id": "parent.name"
},
{
"id": "name"
},
{
"id": "type"
},
{
"id": "information"
}
]
}
]
}
]
},
"selection_loop": [
{
"name": "HostsLoop",
"source": "%(http.tables.resourcesRequestEntries)",
"filter": "%(resourcesRequestEntries.type) eq 'host'",
"formatting": {
"display_ok": "false",
"printf_msg": "Host %s's output is '%s'",
"printf_var": [
"%(resourcesRequestEntries.name)",
"%(resourcesRequestEntries.information)"
]
},
"warning": "%(resourcesRequestEntries.information) =~ /No output returned from plugin|Execute command failed/"
},
{
"name": "ServicesLoop",
"source": "%(http.tables.resourcesRequestEntries)",
"filter": "%(resourcesRequestEntries.type) eq 'service'",
"formatting": {
"display_ok": "false",
"printf_msg": "Service %s/%s output is '%s'",
"printf_var": [
"%(resourcesRequestEntries.parent.name)",
"%(resourcesRequestEntries.name)",
"%(resourcesRequestEntries.information)"
]
},
"warning": "%(resourcesRequestEntries.information) =~ /No output returned from plugin|Execute command failed/"
}
],
"selection": [
{
"name": "totalSelection",
"functions": [
{
"type": "assign",
"expression": "%(http.tables.resourcesRequestMeta.[0].total)",
"save": "%(brokenCommandsCount)"
}
],
"perfdatas": [
{
"nlabel": "commands.broken.count",
"value": "%(brokenCommandsCount)",
"warning": "0",
"min": 0
}
],
"exit": "%(brokenCommandsCount) == 0",
"warning": "%(brokenCommandsCount) > 0",
"formatting_warning": {
"printf_msg": "",
"display_ok": false,
"separator": " "
},
"formatting": {
"printf_msg": "All commands are fine",
"display_ok": true,
"separator": ""
}
}
]
}

View File

@ -0,0 +1,132 @@
{
"constants": {
"protocol": "https",
"port": "443",
"customPath": "centreon"
},
"http": {
"requests": [
{
"name": "authenticationRequest",
"hostname": "%(constants.hostname)",
"proto": "%(constants.protocol)",
"port": "%(constants.port)",
"endpoint": "/%(constants.customPath)/api/latest/login",
"method": "POST",
"headers": [
"Accept:application/json",
"Content-Type:application/json"
],
"timeout": 30,
"payload": {
"type": "json",
"value": {
"security": {
"credentials": {
"login": "%(constants.username)",
"password": "%(constants.password)"
}
}
}
},
"scenario_stopped": "%(builtin.httpCode.authenticationRequest) != 200",
"backend": "curl",
"rtype": "json",
"parse": [
{
"name": "token",
"path": "$.security.token",
"entries": [
{
"id": "value"
}
]
}
]
},
{
"name": "hostsRequest",
"hostname": "%(constants.hostname)",
"proto": "%(constants.protocol)",
"port": "%(constants.port)",
"endpoint": "/%(constants.customPath)/api/latest/monitoring/hosts?limit=1000",
"method": "GET",
"headers": [
"X-AUTH-TOKEN: %(http.tables.authenticationRequestToken.[0].value)",
"Accept: text/json"
],
"timeout": 30,
"backend": "curl",
"rtype": "json",
"parse": [
{
"name": "entries",
"type": "body",
"path": "$.result[*]",
"entries": [
{
"id": "name"
},
{
"id": "state"
}
]
}
]
}
]
},
"selection": [
{
"name": "authenticationSelection",
"critical": "defined(%(builtin.httpCode.authenticationRequest)) and %(builtin.httpCode.authenticationRequest) != 200",
"exit": "defined(%(builtin.httpCode.authenticationRequest)) and %(builtin.httpCode.authenticationRequest) != 200",
"formatting": {
"printf_msg": "Authentication resulted in %s HTTP code",
"printf_var": [
"%(builtin.httpCode.authenticationRequest)"
],
"display_ok": false
}
},
{
"name": "hostsSelection",
"functions": [
{
"type": "count",
"src": "%(http.tables.hostsRequestEntries)",
"filter": "%(src.state) != 0",
"save": "%(downCount)"
},
{
"type": "count",
"src": "%(http.tables.hostsRequestEntries)",
"save": "%(hostsCount)"
}
],
"perfdatas": [
{
"nlabel": "hostsRequest.down.count",
"value": "%(downCount)",
"warning": "0",
"min": 0,
"max": "%(hostsCount)"
}
],
"warning": "%(downCount) > 0",
"formatting": {
"printf_msg": "Number of down hosts: %s out of %s",
"printf_var": [
"%(downCount)",
"%(hostsCount)"
],
"display_ok": true
}
}
],
"formatting": {
"custom_message_global": "All hosts are UP",
"separator": "-"
}
}

View File

@ -0,0 +1,210 @@
{
"uuid": "919382d8-0f30-447f-abcd-45c98e84d7fe",
"lastMigration": 32,
"name": "Centreon web mock for tests of HTTP Collections",
"endpointPrefix": "",
"latency": 0,
"port": 3001,
"hostname": "",
"folders": [],
"routes": [
{
"uuid": "82abcb5a-0a65-409f-badd-5e881b6786df",
"type": "http",
"documentation": "Authentication request",
"method": "post",
"endpoint": "centreon/api/latest/login",
"responses": [
{
"uuid": "b4229c90-76b3-4f8c-be0f-aceeb5566051",
"body": "{}",
"latency": 0,
"statusCode": 200,
"label": "",
"headers": [
{
"key": "content-type",
"value": "application/json; charset=utf-8"
},
{
"key": "content-length",
"value": "2"
}
],
"bodyType": "DATABUCKET",
"filePath": "",
"databucketID": "0ibb",
"sendFileAsBody": false,
"rules": [],
"rulesOperator": "OR",
"disableTemplating": false,
"fallbackTo404": false,
"default": false,
"crudKey": "id",
"callbacks": []
}
],
"responseMode": null
},
{
"uuid": "d67aa94e-09c5-434d-b00a-e9e147e90220",
"type": "http",
"documentation": "Monitoring of hosts, used to look for down hosts",
"method": "get",
"endpoint": "centreon/api/latest/monitoring/hosts",
"responses": [
{
"uuid": "c98ea5bd-143b-414e-ae28-d094e7059682",
"body": "",
"latency": 0,
"statusCode": 200,
"label": "",
"headers": [
{
"key": "content-security-policy",
"value": "default-src 'none'"
},
{
"key": "content-type",
"value": "text/html; charset=utf-8"
},
{
"key": "x-content-type-options",
"value": "nosniff"
}
],
"bodyType": "DATABUCKET",
"filePath": "",
"databucketID": "fdau",
"sendFileAsBody": false,
"rules": [],
"rulesOperator": "OR",
"disableTemplating": false,
"fallbackTo404": false,
"default": false,
"crudKey": "id",
"callbacks": []
}
],
"responseMode": null
},
{
"uuid": "9622753c-4c89-4f37-aa27-6088a4c5557a",
"type": "http",
"documentation": "Monitoring of resources, used to look for broken commands",
"method": "get",
"endpoint": "centreon/api/latest/monitoring/resources",
"responses": [
{
"uuid": "1d5391f0-9edc-4b84-b9ed-b78524ae1782",
"latency": 0,
"statusCode": 200,
"label": "",
"headers": [
{
"key": "content-security-policy",
"value": "default-src 'none'"
},
{
"key": "content-type",
"value": "text/html; charset=utf-8"
},
{
"key": "x-content-type-options",
"value": "nosniff"
}
],
"bodyType": "DATABUCKET",
"filePath": "",
"databucketID": "tpm8",
"sendFileAsBody": false,
"rules": [],
"rulesOperator": "OR",
"disableTemplating": false,
"fallbackTo404": false,
"default": false,
"crudKey": "id",
"callbacks": [],
"body": "{}"
}
],
"responseMode": null
}
],
"rootChildren": [
{
"type": "route",
"uuid": "82abcb5a-0a65-409f-badd-5e881b6786df"
},
{
"type": "route",
"uuid": "d67aa94e-09c5-434d-b00a-e9e147e90220"
},
{
"type": "route",
"uuid": "9622753c-4c89-4f37-aa27-6088a4c5557a"
}
],
"proxyMode": false,
"proxyHost": "",
"proxyRemovePrefix": false,
"tlsOptions": {
"enabled": false,
"type": "CERT",
"pfxPath": "",
"certPath": "",
"keyPath": "",
"caPath": "",
"passphrase": ""
},
"cors": true,
"headers": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"proxyReqHeaders": [
{
"key": "",
"value": ""
}
],
"proxyResHeaders": [
{
"key": "",
"value": ""
}
],
"data": [
{
"uuid": "497b64fa-7c29-4741-8c57-c818aafc9482",
"id": "fdcz",
"name": "Authentication payload",
"documentation": "Authentication payload",
"value": "{\"security\":{\"credentials\":{\"password\":\"***\",\"login\":\"admin\"}}}"
},
{
"uuid": "e9b76766-90a5-496e-8102-3941d22feb32",
"id": "0ibb",
"name": "Authentication response",
"documentation": "Authentication response",
"value": "{\n \"security\" : {\n \"token\" : \"Vj77k9p53L+FTXon1UDvaYBZU8P3MnUK2siU7mst3HJ1QcnjTDWVW6TX3RlccjpV\"\n },\n \"contact\" : {\n \"name\" : \"Administrateur_Centreon\",\n \"is_admin\" : true,\n \"email\" : \"null@localhost.local\",\n \"alias\" : \"admin\",\n \"id\" : 1\n }\n}"
},
{
"uuid": "18e9cb4a-d822-44cd-b6a3-83dbead20130",
"id": "fdau",
"name": "Monitoring/hosts response",
"documentation": "Monitoring/hosts response to count down hosts",
"value": "{\n \"meta\": {\n \"search\": {},\n \"total\": 1,\n \"limit\": 1000,\n \"sort_by\": {},\n \"page\": 1\n },\n \"result\": [\n {\n \"passive_checks\": false,\n \"timezone\": \"\",\n \"last_check\": \"2023-11-21T21:21:14+01:00\",\n \"checked\": true,\n \"state\": 0,\n \"last_time_up\": \"2023-11-21T21:21:18+01:00\",\n \"icon_image\": \"ppm/applications-monitoring-centreon-central-centreon-128-2.png\",\n \"icon_image_alt\": \"\",\n \"state_type\": 1,\n \"address_ip\": \"127.0.0.1\",\n \"criticality\": null,\n \"last_time_down\": null,\n \"scheduled_downtime_depth\": 0,\n \"name\": \"CENTREON\",\n \"last_time_unreachable\": null,\n \"alias\": \"Centreon Central Server\",\n \"poller_id\": 1,\n \"last_hard_state_change\": \"2023-09-07T20:03:53+02:00\",\n \"execution_time\": 0.112673,\n \"last_state_change\": \"2023-09-07T20:03:53+02:00\",\n \"output\": \"OK - 127.0.0.1 rta 0.079ms lost 0%\\n\",\n \"id\": 13,\n \"max_check_attempts\": 3,\n \"last_update\": \"2023-11-21T08:57:13+01:00\",\n \"acknowledged\": false,\n \"display_name\": \"CENTREON\",\n \"check_attempt\": 1\n }\n ]\n}"
},
{
"uuid": "0fcda655-3209-4726-8ab2-18f93666b57c",
"id": "tpm8",
"name": "Monitoring/resources response",
"documentation": "Monitoring/resources response to check errors in commands",
"value": "{\n \"meta\" : {\n \"page\" : 1,\n \"sort_by\" : {},\n \"search\" : {\n \"$and\" : {\n \"information\" : {\n \"$eq\" : \"(Execute command failed)\"\n }\n }\n },\n \"limit\" : 1000,\n \"total\" : 1\n },\n \"result\" : [\n {\n \"uuid\" : \"h254-s1616\",\n \"host_id\" : 254,\n \"monitoring_server_name\" : \"Central\",\n \"status\" : {\n \"name\" : \"UNKNOWN\",\n \"code\" : 3,\n \"severity_code\" : 3\n },\n \"icon\" : null,\n \"alias\" : null,\n \"last_status_change\" : \"2023-11-22T11:55:30+01:00\",\n \"short_type\" : \"s\",\n \"name\" : \"Svc-BadCommand\",\n \"last_check\" : \"1m 2s\",\n \"duration\" : \"4h 28m\",\n \"acknowledged\" : false,\n \"in_downtime\" : false,\n \"chart_url\" : null,\n \"tries\" : \"1/3 (H)\",\n \"information\" : \"(Execute command failed)\",\n \"performance_data\" : null,\n \"parent\" : {\n \"status\" : {\n \"severity_code\" : 1,\n \"name\" : \"DOWN\",\n \"code\" : 1\n },\n \"host_id\" : null,\n \"uuid\" : \"h254\",\n \"alias\" : \"Down\",\n \"icon\" : null,\n \"links\" : {\n \"externals\" : {\n \"action_url\" : null,\n \"notes\" : null\n },\n \"uris\" : {\n \"configuration\" : null,\n \"reporting\" : null,\n \"logs\" : null\n },\n \"endpoints\" : {}\n },\n \"id\" : 254,\n \"fqdn\" : \"1.2.3.4\",\n \"name\" : \"FakeHostThatIsDown\",\n \"type\" : \"host\",\n \"short_type\" : \"h\",\n \"service_id\" : null\n },\n \"links\" : {\n \"externals\" : {\n \"action_url\" : \"\",\n \"notes\" : {\n \"url\" : \"\",\n \"label\" : \"\"\n }\n },\n \"uris\" : {\n \"logs\" : \"/centreon/main.php?p=20301&svc=254_1616\",\n \"configuration\" : \"/centreon/main.php?p=60201&o=c&service_id=1616\",\n \"reporting\" : \"/centreon/main.php?p=30702&period=yesterday&start=&end=&host_id=254&item=1616\"\n },\n \"endpoints\" : {\n \"check\" : \"/centreon/api/latest/monitoring/hosts/254/services/1616/check\",\n \"acknowledgement\" : \"/centreon/api/latest/monitoring/hosts/254/services/1616/acknowledgements?limit=1\",\n \"timeline\" : \"/centreon/api/latest/monitoring/hosts/254/services/1616/timeline\",\n \"performance_graph\" : null,\n \"downtime\" : \"/centreon/api/latest/monitoring/hosts/254/services/1616/downtimes?search=%7B%22%24and%22:%5B%7B%22start_time%22:%7B%22%24lt%22:1700666614%7D,%22end_time%22:%7B%22%24gt%22:1700666614%7D,%220%22:%7B%22%24or%22:%7B%22is_cancelled%22:%7B%22%24neq%22:1%7D,%22deletion_time%22:%7B%22%24gt%22:1700666614%7D%7D%7D%7D%5D%7D\",\n \"forced_check\" : \"/centreon/api/latest/monitoring/hosts/254/services/1616/check\",\n \"status_graph\" : \"/centreon/api/latest/monitoring/hosts/254/services/1616/metrics/status\",\n \"details\" : \"/centreon/api/latest/monitoring/resources/hosts/254/services/1616\"\n }\n },\n \"passive_checks\" : false,\n \"notification_enabled\" : false,\n \"service_id\" : 1616,\n \"type\" : \"service\",\n \"severity\" : null,\n \"fqdn\" : null,\n \"active_checks\" : true,\n \"id\" : 1616\n }\n ]\n}"
}
],
"callbacks": []
}

View File

@ -0,0 +1,34 @@
*** Settings ***
Documentation Collections of HTTP Protocol plugin testing a mock of Centreon-web API
Resource ${CURDIR}${/}..${/}..${/}..${/}..${/}resources/import.resource
Suite Setup Start Mockoon ${MOCKOON_JSON}
Suite Teardown Stop Mockoon
Test Timeout 120s
*** Variables ***
${MOCKOON_JSON} ${CURDIR}${/}collection-centreon-web.mockoon.json
${CMD} ${CENTREON_PLUGINS} --plugin apps::protocols::http::plugin --mode collection
... --constant='hostname=127.0.0.1' --constant='protocol=http' --constant='port=3000'
... --constant='username=admin' --constant='password=myPassword'
*** Test Cases ***
Check if ${test_desc} on Centreon
[Tags] Centreon Collections HTTP
${output} Run
... ${CMD} --config=${CURDIR}/${collection}
${output} Strip String ${output}
Should Be Equal As Strings
... ${output}
... ${expected}
... Wrong output result:\n\n ${output}\nInstead of:\n ${expected}\n\n
Examples: test_desc collection expected --
... authentication succeeds collection-centreon-web-check-auth.collection.json OK: Authentication resulted in 200 HTTP code
... hosts are down collection-centreon-web-check-down-hosts.collection.json OK: All hosts are UP | 'hostsRequest.down.count'=0;0;;0;1
... commands are broken collection-centreon-web-check-broken-commands.collection.json WARNING:${SPACE} - Service FakeHostThatIsDown/Svc-BadCommand output is '(Execute command failed)' | 'commands.broken.count'=1;0;;0;