Skip to content

Commit

Permalink
feat(exit-code): configure exit code for critical on api and command
Browse files Browse the repository at this point in the history
  • Loading branch information
tuxes3 committed Jul 10, 2023
1 parent 150ac42 commit 6fb5094
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 14 deletions.
10 changes: 4 additions & 6 deletions src/Command/CheckCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use whatwedo\MonitorBundle\Manager\MonitoringManager;
use whatwedo\MonitorBundle\Monitoring\Metric\AbstractMetric;
use whatwedo\MonitorBundle\Monitoring\Sensor\AbstractSensor;
use whatwedo\MonitorBundle\Util\StatusCodeDecider;

#[AsCommand(
name: 'whatwedo:monitor:check',
Expand All @@ -21,6 +22,7 @@ class CheckCommand extends Command
{
public function __construct(
protected int $warningExitCode,
protected int $criticalExitCode,
protected MonitoringManager $monitoringManager
) {
parent::__construct();
Expand All @@ -31,12 +33,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$io = new SymfonyStyle($input, $output);
$this->printResult($io, $this->monitoringManager->getResult());

if ($this->monitoringManager->isSuccessful() && $this->monitoringManager->isWarning()) {
return $this->warningExitCode;
} elseif ($this->monitoringManager->isSuccessful()) {
return self::SUCCESS;
}
return self::FAILURE;
$decider = new StatusCodeDecider($this->monitoringManager, self::SUCCESS, $this->warningExitCode, $this->criticalExitCode);
return $decider->decide();
}

private function printResult(SymfonyStyle $io, $result, $previousGroup = null, $level = 0): void
Expand Down
6 changes: 5 additions & 1 deletion src/Controller/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
use Symfony\Component\Serializer\Encoder\JsonEncode;
use Symfony\Component\Serializer\SerializerInterface;
use whatwedo\MonitorBundle\Manager\MonitoringManager;
use whatwedo\MonitorBundle\Util\StatusCodeDecider;

class ApiController extends AbstractController
{
public function __construct(
protected int $warningExitCode,
protected int $criticalExitCode,
protected ?string $authToken = null
) {
}
Expand All @@ -25,11 +28,12 @@ public function __invoke(Request $request, MonitoringManager $monitoringManager,
return new Response('Unauthorized', 401);
}

$decider = new StatusCodeDecider($monitoringManager, Response::HTTP_OK, $this->warningExitCode, $this->criticalExitCode);
return new Response(
$serializer->serialize($monitoringManager->getResult(), $request->attributes->get('_format'), [
JsonEncode::OPTIONS => $request->query->has('pretty') ? JSON_PRETTY_PRINT : 0,
]),
$monitoringManager->isSuccessful() ? Response::HTTP_OK : Response::HTTP_SERVICE_UNAVAILABLE,
$decider->decide(),
[
'Content-type' => match ($request->attributes->get('_format')) {
'json' => 'application/json',
Expand Down
28 changes: 24 additions & 4 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ public function getConfigTreeBuilder(): TreeBuilder
->defaultNull()
->info('Auth token for the api endpoint, must be sent with the X-Auth-Token HTTP header (default null / disabled)')
->end()
->arrayNode('http_status_code')
->children()
->integerNode('warning')
->defaultValue(503)
->info('HTTP status code for warning state (default 503)')
->end()
->integerNode('critical')
->defaultValue(503)
->info('HTTP status code for critical state (default 503)')
->end()
->end()
->end()
->end()
->end()
->arrayNode('controller')
Expand All @@ -48,6 +60,18 @@ public function getConfigTreeBuilder(): TreeBuilder
->defaultTrue()
->info('Enable the command endpoint (default true)')
->end()
->arrayNode('exit_code')
->children()
->integerNode('warning')
->defaultValue(1)
->info('Exit code for warning state (default 1)')
->end()
->integerNode('critical')
->defaultValue(1)
->info('Exit code for critical state (default 1)')
->end()
->end()
->end()
->end()
->end()
->end()
Expand Down Expand Up @@ -75,10 +99,6 @@ public function getConfigTreeBuilder(): TreeBuilder
->end()
->end()
->end()
->integerNode('warning_exit_code')
->defaultValue(1)
->info('Exit code for warning state (default 1)')
->end()
->end()
;

Expand Down
8 changes: 6 additions & 2 deletions src/DependencyInjection/whatwedoMonitorExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ public function configureEndpoints(ContainerBuilder $container, array $config)
{
// register API
$container->findDefinition(ApiController::class)
->addArgument($config['endpoint']['api']['auth_token'] ?? null);
->addArgument($config['endpoint']['api']['exit_code']['warning'] ?? 503)
->addArgument($config['endpoint']['api']['exit_code']['critical'] ?? 503)
->addArgument($config['endpoint']['api']['auth_token'] ?? null)
;

if (isset($config['endpoint']['api']['enabled'])
&& ! $config['endpoint']['api']['enabled']) {
Expand Down Expand Up @@ -70,7 +73,8 @@ public function configureMonitoring(ContainerBuilder $container, array $config)
if (!(isset($config['endpoint']['command']['enabled'])
&& ! $config['endpoint']['command']['enabled'])) {
$container->findDefinition(CheckCommand::class)
->setArgument(0, $config['warning_exit_code'] ?? 1)
->setArgument(0, $config['endpoint']['command']['exit_code']['warning'] ?? 1)
->setArgument(1, $config['endpoint']['command']['exit_code']['critical'] ?? 1)
;
}
}
Expand Down
54 changes: 54 additions & 0 deletions src/Util/StatusCodeDecider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);
/*
* Copyright (c) 2023, whatwedo GmbH
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

namespace whatwedo\MonitorBundle\Util;

use whatwedo\MonitorBundle\Manager\MonitoringManager;

class StatusCodeDecider
{
public function __construct(
protected MonitoringManager $monitoringManager,
protected int $successStatusCode,
protected int $warningStatusCode,
protected int $criticalStatusCode
) {
}

public function decide(): int
{
if ($this->monitoringManager->isSuccessful() && $this->monitoringManager->isWarning()) {
return $this->warningStatusCode;
} elseif ($this->monitoringManager->isSuccessful()) {
return $this->successStatusCode;
}

return $this->criticalStatusCode;
}
}
15 changes: 15 additions & 0 deletions tests/Command/CheckCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,21 @@ public function testCritical(): void
self::assertEquals(1, $commandTester->getStatusCode());
}

public function testCriticalCustomExitCode(): void
{
$kernel = self::bootKernel([
'config' => static function (TestKernel $kernel) {
$kernel->addTestConfig(__DIR__.'/../config/dummy_critical_custom_exit_code.yml');
},
]);
$application = new Application($kernel);
$command = $application->find('whatwedo:monitor:check');

$commandTester = new CommandTester($command);
$commandTester->execute([]);
self::assertEquals(-1, $commandTester->getStatusCode());
}

public function testRuntimeError(): void
{
$kernel = self::bootKernel([
Expand Down
12 changes: 12 additions & 0 deletions tests/config/dummy_critical_custom_exit_code.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
services:
whatwedo\MonitorBundle\Tests\Monitoring\Sensor\Dummy\CriticalDummySensor:
tags: [ 'whatwedo_monitor.attribute' ]

whatwedo\MonitorBundle\Tests\Monitoring\Metric\Dummy\CriticalDummyMetric:
tags: [ 'whatwedo_monitor.attribute' ]

whatwedo_monitor:
endpoint:
command:
exit_code:
critical: -1
5 changes: 4 additions & 1 deletion tests/config/dummy_warning_custom_exit_code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@ services:
tags: [ 'whatwedo_monitor.attribute' ]

whatwedo_monitor:
warning_exit_code: 2
endpoint:
command:
exit_code:
warning: 2

0 comments on commit 6fb5094

Please sign in to comment.