diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2e2f690
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/app/.phpunit.result.cache
+/.phpunit.result.cache
diff --git a/app/.gitignore b/app/.gitignore
index cc1eb0b..f6ed8cb 100644
--- a/app/.gitignore
+++ b/app/.gitignore
@@ -1,3 +1,2 @@
/.env
-/.phpunit.result.cache
/phpunit.xml
diff --git a/app/composer.json b/app/composer.json
index 817f300..3aadfdd 100644
--- a/app/composer.json
+++ b/app/composer.json
@@ -10,12 +10,16 @@
"doctrine/annotations": "^1.13",
"guzzlehttp/guzzle": "^7.3",
"nelmio/api-doc-bundle": "^4.6",
+ "phpdocumentor/reflection-docblock": "^5.2",
"symfony/asset": "5.3.*",
"symfony/console": "5.3.*",
"symfony/dotenv": "5.3.*",
"symfony/flex": "^1.16",
"symfony/framework-bundle": "5.3.*",
+ "symfony/property-access": "5.3.*",
+ "symfony/property-info": "5.3.*",
"symfony/runtime": "5.3.*",
+ "symfony/serializer": "5.3.*",
"symfony/twig-bundle": "5.3.*",
"symfony/yaml": "5.3.*",
"twig/extra-bundle": "^2.12 || ^3.0",
@@ -79,6 +83,10 @@
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd"
},
+ "cs:fix": [
+ "@json-cs-fix",
+ "@php-cs-fix"
+ ],
"json-cs-fix": "composer normalize",
"lint:php": [
"parallel-lint --no-progress --no-colors --blame ./bin/console",
diff --git a/app/composer.lock b/app/composer.lock
index add63c3..9f4142c 100644
--- a/app/composer.lock
+++ b/app/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "42ca436544abf8d5ea35614dcf79d64e",
+ "content-hash": "1fa5d80ef6ea75d8cbdc00ef247597e7",
"packages": [
{
"name": "doctrine/annotations",
@@ -3114,6 +3114,87 @@
],
"time": "2021-05-21T13:25:03+00:00"
},
+ {
+ "name": "symfony/property-access",
+ "version": "v5.3.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/property-access.git",
+ "reference": "2fbab5f95ddb6b8e85f38a6a8a04a17c0acc4d66"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/property-access/zipball/2fbab5f95ddb6b8e85f38a6a8a04a17c0acc4d66",
+ "reference": "2fbab5f95ddb6b8e85f38a6a8a04a17c0acc4d66",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/deprecation-contracts": "^2.1",
+ "symfony/polyfill-php80": "^1.16",
+ "symfony/property-info": "^5.2"
+ },
+ "require-dev": {
+ "symfony/cache": "^4.4|^5.0"
+ },
+ "suggest": {
+ "psr/cache-implementation": "To cache access methods."
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\PropertyAccess\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides functions to read and write from/to an object or array using a simple string notation",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "access",
+ "array",
+ "extraction",
+ "index",
+ "injection",
+ "object",
+ "property",
+ "property path",
+ "reflection"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/property-access/tree/v5.3.8"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-09-10T11:55:24+00:00"
+ },
{
"name": "symfony/property-info",
"version": "v5.3.7",
@@ -3371,6 +3452,108 @@
],
"time": "2021-06-30T13:49:12+00:00"
},
+ {
+ "name": "symfony/serializer",
+ "version": "v5.3.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/serializer.git",
+ "reference": "a877799b1e94f792208bea68295f6675027c92be"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/serializer/zipball/a877799b1e94f792208bea68295f6675027c92be",
+ "reference": "a877799b1e94f792208bea68295f6675027c92be",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.5",
+ "symfony/deprecation-contracts": "^2.1",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-php80": "^1.16"
+ },
+ "conflict": {
+ "doctrine/annotations": "<1.12",
+ "phpdocumentor/reflection-docblock": "<3.2.2",
+ "phpdocumentor/type-resolver": "<1.4.0",
+ "symfony/dependency-injection": "<4.4",
+ "symfony/property-access": "<4.4",
+ "symfony/property-info": "<5.3",
+ "symfony/yaml": "<4.4"
+ },
+ "require-dev": {
+ "doctrine/annotations": "^1.12",
+ "phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0",
+ "symfony/cache": "^4.4|^5.0",
+ "symfony/config": "^4.4|^5.0",
+ "symfony/dependency-injection": "^4.4|^5.0",
+ "symfony/error-handler": "^4.4|^5.0",
+ "symfony/filesystem": "^4.4|^5.0",
+ "symfony/form": "^4.4|^5.0",
+ "symfony/http-foundation": "^4.4|^5.0",
+ "symfony/http-kernel": "^4.4|^5.0",
+ "symfony/mime": "^4.4|^5.0",
+ "symfony/property-access": "^4.4.9|^5.0.9",
+ "symfony/property-info": "^5.3",
+ "symfony/uid": "^5.1",
+ "symfony/validator": "^4.4|^5.0",
+ "symfony/var-dumper": "^4.4|^5.0",
+ "symfony/var-exporter": "^4.4|^5.0",
+ "symfony/yaml": "^4.4|^5.0"
+ },
+ "suggest": {
+ "psr/cache-implementation": "For using the metadata cache.",
+ "symfony/config": "For using the XML mapping loader.",
+ "symfony/mime": "For using a MIME type guesser within the DataUriNormalizer.",
+ "symfony/property-access": "For using the ObjectNormalizer.",
+ "symfony/property-info": "To deserialize relations.",
+ "symfony/var-exporter": "For using the metadata compiler.",
+ "symfony/yaml": "For using the default YAML mapping loader."
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Symfony\\Component\\Serializer\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.",
+ "homepage": "https://symfony.com",
+ "support": {
+ "source": "https://github.com/symfony/serializer/tree/v5.3.8"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-09-17T08:55:39+00:00"
+ },
{
"name": "symfony/service-contracts",
"version": "v2.4.0",
@@ -5965,7 +6148,7 @@
"ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6",
"ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1",
"ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<=1.3.1",
- "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<=1.3.1",
+ "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8",
"ezsystems/ezplatform-user": ">=1,<1.0.1",
"ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<=7.5.15.1",
"ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.3.5.1",
@@ -5990,13 +6173,14 @@
"friendsoftypo3/mediace": ">=7.6.2,<7.6.5",
"froala/wysiwyg-editor": "<3.2.7",
"fuel/core": "<1.8.1",
- "getgrav/grav": "<=1.7.10",
+ "getgrav/grav": "<1.7.21",
"getkirby/cms": "<=3.5.6",
"getkirby/panel": "<2.5.14",
+ "gilacms/gila": "<=1.11.4",
"gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3",
"gree/jose": "<=2.2",
"gregwar/rst": "<1.0.3",
- "grumpydictator/firefly-iii": "<5.6",
+ "grumpydictator/firefly-iii": "<5.6.1",
"guzzlehttp/guzzle": ">=4-rc.2,<4.2.4|>=5,<5.3.1|>=6,<6.2.1",
"helloxz/imgurl": "<=2.31",
"ibexa/post-install": "<=1.0.4",
@@ -6023,6 +6207,7 @@
"laravel/framework": "<6.20.26|>=7,<8.40",
"laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10",
"lavalite/cms": "<=5.8",
+ "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5",
"league/commonmark": "<0.18.3",
"league/flysystem": "<1.1.4|>=2,<2.1.1",
"lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3",
@@ -6186,6 +6371,7 @@
"theonedemon/phpwhois": "<=4.2.5",
"titon/framework": ">=0,<9.9.99",
"topthink/think": "<=6.0.9",
+ "topthink/thinkphp": "<=3.2.3",
"tribalsystems/zenario": "<8.8.53370",
"truckersmp/phpwhois": "<=4.3.1",
"twig/twig": "<1.38|>=2,<2.7",
@@ -6204,6 +6390,7 @@
"verot/class.upload.php": "<=1.0.3|>=2,<=2.0.4",
"vrana/adminer": "<4.7.9",
"wallabag/tcpdf": "<6.2.22",
+ "web-auth/webauthn-framework": ">=3.3,<3.3.4",
"webcoast/deferred-image-processing": "<1.0.2",
"wikimedia/parsoid": "<0.12.2",
"willdurand/js-translation-bundle": "<2.1.1",
diff --git a/app/src/Controller/Api/v1/MattermostController.php b/app/src/Controller/Api/v1/MattermostController.php
index f163402..718a477 100644
--- a/app/src/Controller/Api/v1/MattermostController.php
+++ b/app/src/Controller/Api/v1/MattermostController.php
@@ -4,49 +4,68 @@ declare(strict_types=1);
namespace App\Controller\Api\v1;
+use App\Model\Grafana\GrafanaMessage;
use App\Service\Mattermost\MattermostServiceInterface;
+use Nelmio\ApiDocBundle\Annotation\Model;
use OpenApi\Annotations as OA;
+use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
+use Symfony\Component\Serializer\SerializerInterface;
use Throwable;
class MattermostController extends AbstractController
{
+ protected LoggerInterface $logger;
+ protected SerializerInterface $serializer;
protected MattermostServiceInterface $mattermostService;
- public function __construct(MattermostServiceInterface $mattermostService)
- {
+ public function __construct(
+ LoggerInterface $logger,
+ SerializerInterface $serializer,
+ MattermostServiceInterface $mattermostService,
+ ) {
+ $this->logger = $logger;
+ $this->serializer = $serializer;
$this->mattermostService = $mattermostService;
}
/**
- * Send message to a mattermost chat.
+ * Send message to a mattermost chat from grafana.
*
- * Docs https://docs.mattermost.com/developer/webhooks-incoming.html
+ * Docs
+ * - https://grafana.com/docs/grafana/latest/alerting/old-alerting/notifications/#webhook
+ * - https://docs.mattermost.com/developer/webhooks-incoming.html
*
- * @Route("/api/v1/send_message", methods={"POST"})
+ * @Route("/api/v1/send_message/grafana", methods={"POST"})
* @OA\Tag(name="mattermost")
- * @OA\Parameter(
- * name="message",
- * in="query",
- * required=true,
- * @OA\Schema(type="string")
+ * @OA\RequestBody(
+ * @OA\JsonContent(
+ * ref=@Model(type=GrafanaMessage::class)
+ * )
* )
* @OA\Response(
* response=200,
* description="Success delivery"
* )
*/
- public function sendMessage(Request $request): Response
+ public function sendMessageFromGrafana(Request $request): Response
{
try {
- $message = $request->query->get('message');
- $response = $this->mattermostService->sendMessage($message);
+ $this->logger->notice($request->getContent());
+ $message = $this->serializer->deserialize(
+ $request->getContent(),
+ GrafanaMessage::class,
+ 'json'
+ );
+ $response = $this->mattermostService->sendGrafanaMessage($message);
return new Response($response->getBody()->getContents());
} catch (Throwable $e) {
+ $this->logger->critical($e->getMessage());
+
return new Response(
$e->getMessage(),
0 === $e->getCode() ? Response::HTTP_INTERNAL_SERVER_ERROR : $e->getCode()
diff --git a/app/src/Model/Grafana/EvalMatches.php b/app/src/Model/Grafana/EvalMatches.php
new file mode 100644
index 0000000..e39e589
--- /dev/null
+++ b/app/src/Model/Grafana/EvalMatches.php
@@ -0,0 +1,64 @@
+value;
+ }
+
+ public function setValue(int $value): self
+ {
+ $this->value = $value;
+
+ return $this;
+ }
+
+ public function getMetric(): string
+ {
+ return $this->metric;
+ }
+
+ public function setMetric(string $metric): self
+ {
+ $this->metric = $metric;
+
+ return $this;
+ }
+
+ public function getTags(): ?string
+ {
+ return $this->tags;
+ }
+
+ public function setTags(?string $tags): self
+ {
+ $this->tags = $tags;
+
+ return $this;
+ }
+}
diff --git a/app/src/Model/Grafana/GrafanaMessage.php b/app/src/Model/Grafana/GrafanaMessage.php
new file mode 100644
index 0000000..fee06b9
--- /dev/null
+++ b/app/src/Model/Grafana/GrafanaMessage.php
@@ -0,0 +1,211 @@
+dashboardId;
+ }
+
+ public function setDashboardId(int $dashboardId): self
+ {
+ $this->dashboardId = $dashboardId;
+
+ return $this;
+ }
+
+ /**
+ * @return EvalMatches[]
+ */
+ public function getEvalMatches(): array
+ {
+ return $this->evalMatches;
+ }
+
+ /**
+ * @param EvalMatches[] $evalMatches
+ */
+ public function setEvalMatches(array $evalMatches): self
+ {
+ $this->evalMatches = $evalMatches;
+
+ return $this;
+ }
+
+ public function getImageUrl(): string
+ {
+ return $this->imageUrl;
+ }
+
+ public function setImageUrl(string $imageUrl): self
+ {
+ $this->imageUrl = $imageUrl;
+
+ return $this;
+ }
+
+ public function getMessage(): string
+ {
+ return $this->message;
+ }
+
+ public function setMessage(string $message): self
+ {
+ $this->message = $message;
+
+ return $this;
+ }
+
+ public function getOrgId(): int
+ {
+ return $this->orgId;
+ }
+
+ public function setOrgId(int $orgId): self
+ {
+ $this->orgId = $orgId;
+
+ return $this;
+ }
+
+ public function getPanelId(): int
+ {
+ return $this->panelId;
+ }
+
+ public function setPanelId(int $panelId): self
+ {
+ $this->panelId = $panelId;
+
+ return $this;
+ }
+
+ public function getRuleId(): int
+ {
+ return $this->ruleId;
+ }
+
+ public function setRuleId(int $ruleId): self
+ {
+ $this->ruleId = $ruleId;
+
+ return $this;
+ }
+
+ public function getRuleName(): string
+ {
+ return $this->ruleName;
+ }
+
+ public function setRuleName(string $ruleName): self
+ {
+ $this->ruleName = $ruleName;
+
+ return $this;
+ }
+
+ public function getRuleUrl(): string
+ {
+ return $this->ruleUrl;
+ }
+
+ public function setRuleUrl(string $ruleUrl): self
+ {
+ $this->ruleUrl = $ruleUrl;
+
+ return $this;
+ }
+
+ public function getState(): string
+ {
+ return $this->state;
+ }
+
+ public function setState(string $state): self
+ {
+ $this->state = $state;
+
+ return $this;
+ }
+
+ public function getTitle(): string
+ {
+ return $this->title;
+ }
+
+ public function setTitle(string $title): self
+ {
+ $this->title = $title;
+
+ return $this;
+ }
+}
diff --git a/app/src/Service/Mattermost/MattermostService.php b/app/src/Service/Mattermost/MattermostService.php
index 84d0f52..3173cc5 100644
--- a/app/src/Service/Mattermost/MattermostService.php
+++ b/app/src/Service/Mattermost/MattermostService.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace App\Service\Mattermost;
+use App\Model\Grafana\GrafanaMessage;
use App\Service\BaseService;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Psr7\Request;
@@ -34,10 +35,17 @@ class MattermostService extends BaseService implements MattermostServiceInterfac
* @throws GuzzleException
* @throws \JsonException
*/
- public function sendMessage(string $message): ResponseInterface
+ public function sendGrafanaMessage(GrafanaMessage $grafanaMessage): ResponseInterface
{
$request = new Request('POST', $this->mattermostUri);
+ $text = sprintf(
+ "%s\n %s\n %s\n\n",
+ $grafanaMessage->getTitle(),
+ $grafanaMessage->getMessage(),
+ $grafanaMessage->getImageUrl()
+ );
+
$options = [
'headers' => [
'Content-Type' => 'application/json',
@@ -46,7 +54,7 @@ class MattermostService extends BaseService implements MattermostServiceInterfac
'channel' => $this->channelName,
'username' => $this->botName,
'icon_url' => $this->botIcon,
- 'text' => $message,
+ 'text' => $text,
], JSON_THROW_ON_ERROR),
];
diff --git a/app/src/Service/Mattermost/MattermostServiceInterface.php b/app/src/Service/Mattermost/MattermostServiceInterface.php
index a58753c..7803abb 100644
--- a/app/src/Service/Mattermost/MattermostServiceInterface.php
+++ b/app/src/Service/Mattermost/MattermostServiceInterface.php
@@ -4,9 +4,10 @@ declare(strict_types=1);
namespace App\Service\Mattermost;
+use App\Model\Grafana\GrafanaMessage;
use Psr\Http\Message\ResponseInterface;
interface MattermostServiceInterface
{
- public function sendMessage(string $message): ResponseInterface;
+ public function sendGrafanaMessage(GrafanaMessage $grafanaMessage): ResponseInterface;
}
diff --git a/app/symfony.lock b/app/symfony.lock
index f4c44b4..4fd2912 100644
--- a/app/symfony.lock
+++ b/app/symfony.lock
@@ -345,6 +345,9 @@
"symfony/process": {
"version": "v5.3.7"
},
+ "symfony/property-access": {
+ "version": "v5.3.8"
+ },
"symfony/property-info": {
"version": "v5.3.7"
},
@@ -364,6 +367,9 @@
"symfony/runtime": {
"version": "v5.3.4"
},
+ "symfony/serializer": {
+ "version": "v5.3.8"
+ },
"symfony/service-contracts": {
"version": "v2.4.0"
},
diff --git a/app/tests/Unit/Controller/Api/v1/MattermostControllerTest.php b/app/tests/Unit/Controller/Api/v1/MattermostControllerTest.php
index f61b0b5..ef678c7 100644
--- a/app/tests/Unit/Controller/Api/v1/MattermostControllerTest.php
+++ b/app/tests/Unit/Controller/Api/v1/MattermostControllerTest.php
@@ -8,7 +8,7 @@ use App\Controller\Api\v1\MattermostController;
use App\Tests\Unit\UnitTester;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
-class MattermostControllerTest extends UnitTester
+final class MattermostControllerTest extends UnitTester
{
public function testIsExtends(): void
{
diff --git a/app/tests/Unit/KernelTest.php b/app/tests/Unit/KernelTest.php
index 320b367..d224d4e 100644
--- a/app/tests/Unit/KernelTest.php
+++ b/app/tests/Unit/KernelTest.php
@@ -8,7 +8,7 @@ use App\Kernel;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
-class KernelTest extends TestCase
+final class KernelTest extends TestCase
{
public function testIsExtends(): void
{
diff --git a/app/tests/Unit/Model/Grafana/EvalMatchesTest.php b/app/tests/Unit/Model/Grafana/EvalMatchesTest.php
new file mode 100644
index 0000000..ca8d8a3
--- /dev/null
+++ b/app/tests/Unit/Model/Grafana/EvalMatchesTest.php
@@ -0,0 +1,110 @@
+faker->randomNumber();
+
+ $property = $this->getClassProperty($evalMatches, 'value');
+ $property->setValue($evalMatches, $value);
+
+ self::assertEquals($value, $evalMatches->getValue());
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testSetValue(): void
+ {
+ $evalMatches = new EvalMatches();
+ $value = $this->faker->randomNumber();
+
+ self::assertEquals($evalMatches, $evalMatches->setValue($value));
+ self::assertEquals(
+ $value,
+ ($this->getClassProperty($evalMatches, 'value'))
+ ->getValue($evalMatches)
+ );
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testGetMetric(): void
+ {
+ $evalMatches = new EvalMatches();
+ $value = $this->faker->sha256();
+
+ $property = $this->getClassProperty($evalMatches, 'metric');
+ $property->setValue($evalMatches, $value);
+
+ self::assertEquals($value, $evalMatches->getMetric());
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testSetMetric(): void
+ {
+ $evalMatches = new EvalMatches();
+ $value = $this->faker->sha256();
+
+ self::assertEquals($evalMatches, $evalMatches->setMetric($value));
+ self::assertEquals(
+ $value,
+ ($this->getClassProperty($evalMatches, 'metric'))
+ ->getValue($evalMatches)
+ );
+ }
+
+ /**
+ * @dataProvider dataProviderTags
+ * @throws ReflectionException
+ */
+ public function testGetTags(?string $value): void
+ {
+ $evalMatches = new EvalMatches();
+
+ $property = $this->getClassProperty($evalMatches, 'tags');
+ $property->setValue($evalMatches, $value);
+
+ self::assertEquals($value, $evalMatches->getTags());
+ }
+
+ /**
+ * @dataProvider dataProviderTags
+ * @throws ReflectionException
+ */
+ public function testSetTags(?string $value): void
+ {
+ $evalMatches = new EvalMatches();
+
+ self::assertEquals($evalMatches, $evalMatches->setTags($value));
+ self::assertEquals(
+ $value,
+ ($this->getClassProperty($evalMatches, 'tags'))
+ ->getValue($evalMatches)
+ );
+ }
+
+ public function dataProviderTags(): array
+ {
+ return [
+ ['tags' => null],
+ ['tags' => $this->faker->sha256()],
+ ];
+ }
+}
diff --git a/app/tests/Unit/Model/Grafana/GrafanaMessageTest.php b/app/tests/Unit/Model/Grafana/GrafanaMessageTest.php
new file mode 100644
index 0000000..183b146
--- /dev/null
+++ b/app/tests/Unit/Model/Grafana/GrafanaMessageTest.php
@@ -0,0 +1,313 @@
+faker->randomNumber();
+
+ $property = $this->getClassProperty($grafanaMessage, 'dashboardId');
+ $property->setValue($grafanaMessage, $value);
+
+ self::assertEquals($value, $grafanaMessage->getDashboardId());
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testSetDashboardId(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->randomNumber();
+
+ self::assertEquals($grafanaMessage, $grafanaMessage->setDashboardId($value));
+ self::assertEquals(
+ $value,
+ ($this->getClassProperty($grafanaMessage, 'dashboardId'))
+ ->getValue($grafanaMessage)
+ );
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testGetEvalMatches(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = [new EvalMatches()];
+
+ $property = $this->getClassProperty($grafanaMessage, 'evalMatches');
+ $property->setValue($grafanaMessage, $value);
+
+ self::assertEquals($value, $grafanaMessage->getEvalMatches());
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testSetEvalMatches(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = [new EvalMatches()];
+
+ self::assertEquals($grafanaMessage, $grafanaMessage->setEvalMatches($value));
+ self::assertEquals(
+ $value,
+ ($this->getClassProperty($grafanaMessage, 'evalMatches'))
+ ->getValue($grafanaMessage)
+ );
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testGetImageUrl(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->sha256();
+
+ $property = $this->getClassProperty($grafanaMessage, 'imageUrl');
+ $property->setValue($grafanaMessage, $value);
+
+ self::assertEquals($value, $grafanaMessage->getImageUrl());
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testSetImageUrl(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->sha256();
+
+ self::assertEquals($grafanaMessage, $grafanaMessage->setImageUrl($value));
+ self::assertEquals(
+ $value,
+ ($this->getClassProperty($grafanaMessage, 'imageUrl'))
+ ->getValue($grafanaMessage)
+ );
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testGetMessage(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->sha256();
+
+ $property = $this->getClassProperty($grafanaMessage, 'message');
+ $property->setValue($grafanaMessage, $value);
+
+ self::assertEquals($value, $grafanaMessage->getMessage());
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testSetMessage(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->sha256();
+
+ self::assertEquals($grafanaMessage, $grafanaMessage->setMessage($value));
+ self::assertEquals(
+ $value,
+ ($this->getClassProperty($grafanaMessage, 'message'))
+ ->getValue($grafanaMessage)
+ );
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testGetOrgId(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->randomNumber();
+
+ $property = $this->getClassProperty($grafanaMessage, 'orgId');
+ $property->setValue($grafanaMessage, $value);
+
+ self::assertEquals($value, $grafanaMessage->getOrgId());
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testSetOrgId(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->randomNumber();
+
+ self::assertEquals($grafanaMessage, $grafanaMessage->setOrgId($value));
+ self::assertEquals(
+ $value,
+ ($this->getClassProperty($grafanaMessage, 'orgId'))
+ ->getValue($grafanaMessage)
+ );
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testGetPanelId(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->randomNumber();
+
+ $property = $this->getClassProperty($grafanaMessage, 'panelId');
+ $property->setValue($grafanaMessage, $value);
+
+ self::assertEquals($value, $grafanaMessage->getPanelId());
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testSetPanelId(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->randomNumber();
+
+ self::assertEquals($grafanaMessage, $grafanaMessage->setPanelId($value));
+ self::assertEquals(
+ $value,
+ ($this->getClassProperty($grafanaMessage, 'panelId'))
+ ->getValue($grafanaMessage)
+ );
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testGetRuleId(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->randomNumber();
+
+ $property = $this->getClassProperty($grafanaMessage, 'ruleId');
+ $property->setValue($grafanaMessage, $value);
+
+ self::assertEquals($value, $grafanaMessage->getRuleId());
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testSetRuleId(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->randomNumber();
+
+ self::assertEquals($grafanaMessage, $grafanaMessage->setRuleId($value));
+ self::assertEquals(
+ $value,
+ ($this->getClassProperty($grafanaMessage, 'ruleId'))
+ ->getValue($grafanaMessage)
+ );
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testGetRuleName(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->sha256();
+
+ $property = $this->getClassProperty($grafanaMessage, 'ruleName');
+ $property->setValue($grafanaMessage, $value);
+
+ self::assertEquals($value, $grafanaMessage->getRuleName());
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testSetRuleName(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->sha256();
+
+ self::assertEquals($grafanaMessage, $grafanaMessage->setRuleName($value));
+ self::assertEquals(
+ $value,
+ ($this->getClassProperty($grafanaMessage, 'ruleName'))
+ ->getValue($grafanaMessage)
+ );
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testGetState(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->sha256();
+
+ $property = $this->getClassProperty($grafanaMessage, 'state');
+ $property->setValue($grafanaMessage, $value);
+
+ self::assertEquals($value, $grafanaMessage->getState());
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testSetState(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->sha256();
+
+ self::assertEquals($grafanaMessage, $grafanaMessage->setState($value));
+ self::assertEquals(
+ $value,
+ ($this->getClassProperty($grafanaMessage, 'state'))
+ ->getValue($grafanaMessage)
+ );
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testGetTitle(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->sha256();
+
+ $property = $this->getClassProperty($grafanaMessage, 'title');
+ $property->setValue($grafanaMessage, $value);
+
+ self::assertEquals($value, $grafanaMessage->getTitle());
+ }
+
+ /**
+ * @throws ReflectionException
+ */
+ public function testSetTitle(): void
+ {
+ $grafanaMessage = new GrafanaMessage();
+ $value = $this->faker->sha256();
+
+ self::assertEquals($grafanaMessage, $grafanaMessage->setTitle($value));
+ self::assertEquals(
+ $value,
+ ($this->getClassProperty($grafanaMessage, 'title'))
+ ->getValue($grafanaMessage)
+ );
+ }
+}
diff --git a/app/tests/Unit/Service/Mattermost/MattermostServiceTest.php b/app/tests/Unit/Service/Mattermost/MattermostServiceTest.php
index 71c9ec2..0d1ab8f 100644
--- a/app/tests/Unit/Service/Mattermost/MattermostServiceTest.php
+++ b/app/tests/Unit/Service/Mattermost/MattermostServiceTest.php
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace App\Tests\Unit\Service\Mattermost;
+use App\Model\Grafana\GrafanaMessage;
use App\Service\BaseService;
use App\Service\Mattermost\MattermostService;
use App\Service\Mattermost\MattermostServiceInterface;
@@ -12,8 +13,9 @@ use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
use App\Tests\Unit\UnitTester;
use Psr\Http\Message\ResponseInterface;
+use ReflectionException;
-class MattermostServiceTest extends UnitTester
+final class MattermostServiceTest extends UnitTester
{
public function testIsExtends(): void
{
@@ -30,16 +32,16 @@ class MattermostServiceTest extends UnitTester
}
/**
- * @dataProvider sendMessageDataProvider
- * @throws \ReflectionException
+ * @dataProvider sendGrafanaMessageDataProvider
+ * @throws ReflectionException
*/
- public function testSendMessage(
+ public function testSendGrafanaMessage(
string $mattermostUrl,
string $mattermostUri,
string $channelName,
string $botName,
string $botIcon,
- string $message,
+ GrafanaMessage $grafanaMessage,
array $options
): void
{
@@ -62,20 +64,22 @@ class MattermostServiceTest extends UnitTester
self::assertEquals(
$responseMock,
- $mattermostService->sendMessage($message)
+ $mattermostService->sendGrafanaMessage($grafanaMessage)
);
}
/**
* @throws \JsonException
*/
- public function sendMessageDataProvider(): array
+ public function sendGrafanaMessageDataProvider(): array
{
$faker = (Factory::create('en_EN'));
$channelName = $faker->sha256();
$botName = $faker->sha256();
$botIcon = $faker->sha256();
+ $title = $faker->sha256();
$message = $faker->sha256();
+ $imageUrl = $faker->sha256();
return [
[
@@ -84,7 +88,11 @@ class MattermostServiceTest extends UnitTester
'channelName' => $channelName,
'botName' => $botName,
'botIcon' => $botIcon,
- 'message' => $message,
+ 'message' =>
+ (new GrafanaMessage())
+ ->setTitle($title)
+ ->setMessage($message)
+ ->setImageUrl($imageUrl),
'options' => [
'headers' => [
'Content-Type' => 'application/json',
@@ -93,7 +101,9 @@ class MattermostServiceTest extends UnitTester
'channel' => $channelName,
'username' => $botName,
'icon_url' => $botIcon,
- 'text' => $message,
+ 'text' => sprintf("%s\n %s\n %s\n\n",
+ $title, $message, $imageUrl
+ ),
], JSON_THROW_ON_ERROR),
]
]
diff --git a/app/tests/Unit/UnitTester.php b/app/tests/Unit/UnitTester.php
index 9b6d1b8..c366a33 100644
--- a/app/tests/Unit/UnitTester.php
+++ b/app/tests/Unit/UnitTester.php
@@ -4,6 +4,8 @@ declare(strict_types=1);
namespace App\Tests\Unit;
+use Faker\Factory;
+use Faker\Generator;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
use ReflectionException;
@@ -11,6 +13,14 @@ use ReflectionProperty;
class UnitTester extends TestCase
{
+ protected Generator $faker;
+
+ public function __construct(?string $name = null, array $data = [], $dataName = '')
+ {
+ parent::__construct($name, $data, $dataName);
+ $this->faker = (Factory::create('en_EN'));
+ }
+
/**
* @throws ReflectionException
*/
diff --git a/devops/docker/php/Dockerfile b/devops/docker/php/Dockerfile
index 7cd1273..463ff64 100644
--- a/devops/docker/php/Dockerfile
+++ b/devops/docker/php/Dockerfile
@@ -1,19 +1,13 @@
FROM php:8.0-fpm-alpine3.14 AS base
-
RUN apk update && apk upgrade && \
- apk add --no-cache $PHPIZE_DEPS libzip-dev && \
+ apk add --no-cache $PHPIZE_DEPS libzip-dev composer && \
docker-php-ext-install zip pcntl
-RUN php -r "readfile('https://getcomposer.org/installer');" \
- | php -- --install-dir=/usr/local/bin --version=2.1.6 --filename=composer
-
RUN mkdir -p /var/www/localhost
WORKDIR /var/www/localhost
-COPY ./app .
-
-FROM base AS test
+FROM base AS pre_test
ARG XDEBUG_VERSION=3.0.4
RUN curl --proto =https --tlsv1.2 "https://pecl.php.net/get/xdebug-${XDEBUG_VERSION}.tgz" && \
pecl install xdebug-${XDEBUG_VERSION}.tgz && \
@@ -21,12 +15,15 @@ RUN curl --proto =https --tlsv1.2 "https://pecl.php.net/get/xdebug-${XDEBUG_VERS
rm -rf /tmp/pear && \
docker-php-ext-enable xdebug
COPY devops/docker/php/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini
+
+
+FROM pre_test AS test
+COPY ./app .
COPY env/app/app.env-dist .env
RUN composer install --no-interaction --optimize-autoloader
-FROM test AS local
-
+FROM pre_test AS local
ARG HOME=/home/fedy95
ARG USER=fedy95
ARG UID=1000
diff --git a/devops/docker/php/xdebug.ini b/devops/docker/php/xdebug.ini
index 2ce43e1..53544cd 100644
--- a/devops/docker/php/xdebug.ini
+++ b/devops/docker/php/xdebug.ini
@@ -1,4 +1,3 @@
-zend_extension=xdebug.so
xdebug.client_host=host.docker.internal
xdebug.mode=coverage,debug,profile
xdebug.discover_client_host=1
diff --git a/docker-compose-local.yml b/docker-compose-local.yml
index 9c2a0a3..8f1de49 100644
--- a/docker-compose-local.yml
+++ b/docker-compose-local.yml
@@ -1,6 +1,10 @@
---
version: "3.4"
+networks:
+ monitoring_monitor-net:
+ external: true
+
services:
app:
build:
@@ -11,11 +15,13 @@ services:
environment:
COMPOSER_MEMORY_LIMIT: "-1"
- PHP_IDE_CONFIG: "serverName=notification-provider_php"
+ PHP_IDE_CONFIG: "serverName=notification-provider_app"
volumes:
- ./app:/var/www/localhost
expose:
- "9000"
+ networks:
+ - monitoring_monitor-net
nginx:
image: nginx:1.21-alpine
@@ -28,4 +34,6 @@ services:
- ./devops/docker/nginx/etc/nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf
ports:
- "8054:80"
+ networks:
+ - monitoring_monitor-net
...