From 3bfd65e90979c68a51a4bbe0f94550c73e561b10 Mon Sep 17 00:00:00 2001 From: Nicolas Arenas Date: Mon, 4 Nov 2024 12:02:35 +0100 Subject: [PATCH 1/7] Update yaml to deploy shared volume between php and nginx container --- docker-compose-deploy.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docker-compose-deploy.yml b/docker-compose-deploy.yml index 8f04f0f..36f1181 100644 --- a/docker-compose-deploy.yml +++ b/docker-compose-deploy.yml @@ -13,7 +13,6 @@ services: - database_data:/var/lib/mysql networks: - ogcore-network - nginx: container_name: ogcore-nginx build: @@ -23,8 +22,9 @@ services: - php ports: - 8080:80 + - 8443:443 volumes: - - ./public:/var/www/html/public:cached + - ogpublic:/var/www/html/public:cached networks: - ogcore-network image: opengnsys/ogcore-nginx:static @@ -40,12 +40,15 @@ services: XDEBUG_CLIENT_HOST: 127.17.0.1 XDEBUG_CLIENT_PORT: 9003 PHP_IDE_CONFIG: serverName=ogcore + volumes: + - ogpublic:/var/www/html/public networks: - ogcore-network image: opengnsys/ogcore-php:static volumes: database_data: + ogpublic: networks: ogcore-network: From a2f35e89275b808b4a5341d5f4aa2724d9106167 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Rosales Date: Wed, 20 Nov 2024 19:24:00 +0100 Subject: [PATCH 2/7] Update docker-compose-deploy.yml Fix tipo --- docker-compose-deploy.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docker-compose-deploy.yml b/docker-compose-deploy.yml index acf0ce8..121bcb4 100644 --- a/docker-compose-deploy.yml +++ b/docker-compose-deploy.yml @@ -41,7 +41,6 @@ services: - /opt/opengnsys/ogCore/etc/.env:/var/www/html/.env - /opt/opengnsys/ogCore/etc/env.json://var/www/html/env.json ->>>>>>> develop networks: - ogcore-network image: opengnsys/ogcore-php:static From 4638c07416d6e925b847731c336d5ba4eac0de7f Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Fri, 22 Nov 2024 12:27:12 +0100 Subject: [PATCH 3/7] Big updates dhcp subnets --- .../OgDhcp/AbstractOgDhcpController.php | 5 +++-- src/Controller/OgDhcp/Subnet/DeleteAction.php | 2 +- src/Controller/OgDhcp/Subnet/DeleteHostAction.php | 4 ++-- src/Controller/OgDhcp/Subnet/GetAction.php | 4 ++-- .../OgDhcp/Subnet/GetCollectionAction.php | 4 ++-- src/Controller/OgDhcp/Subnet/GetHostsAction.php | 4 ++-- src/Controller/OgDhcp/Subnet/PostAction.php | 6 +++--- src/Controller/OgDhcp/Subnet/PostHostAction.php | 4 ++-- src/Controller/OgDhcp/Subnet/PutAction.php | 4 ++-- src/Controller/OgDhcp/Subnet/PutHostAction.php | 4 ++-- src/Controller/OgDhcp/Subnet/SyncAction.php | 10 +++++----- src/State/Processor/SubnetProcessor.php | 15 ++++++++++++++- 12 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/Controller/OgDhcp/AbstractOgDhcpController.php b/src/Controller/OgDhcp/AbstractOgDhcpController.php index 9288698..bedb32d 100644 --- a/src/Controller/OgDhcp/AbstractOgDhcpController.php +++ b/src/Controller/OgDhcp/AbstractOgDhcpController.php @@ -26,6 +26,7 @@ abstract class AbstractOgDhcpController extends AbstractController protected readonly string $ogDhcpApiUrl, protected readonly EntityManagerInterface $entityManager, protected readonly GetIpAddressAndNetmaskFromCIDRService $getIpAddressAndNetmaskFromCIDRService, + protected readonly HttpClientInterface $httpClient, ) { } @@ -36,7 +37,7 @@ abstract class AbstractOgDhcpController extends AbstractController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function createRequest (HttpClientInterface $httpClient, string $method, string $url, array $params = []): JsonResponse|array + public function createRequest (string $method, string $url, array $params = []): JsonResponse|array { $params = array_merge($params, [ 'headers' => [ @@ -46,7 +47,7 @@ abstract class AbstractOgDhcpController extends AbstractController ]); try { - $response = $httpClient->request($method, $url, $params); + $response = $this->httpClient->request($method, $url, $params); return json_decode($response->getContent(), true); } catch (ClientExceptionInterface | ServerExceptionInterface $e) { diff --git a/src/Controller/OgDhcp/Subnet/DeleteAction.php b/src/Controller/OgDhcp/Subnet/DeleteAction.php index 7b9554c..6a184f3 100644 --- a/src/Controller/OgDhcp/Subnet/DeleteAction.php +++ b/src/Controller/OgDhcp/Subnet/DeleteAction.php @@ -29,7 +29,7 @@ class DeleteAction extends AbstractOgDhcpController throw new ValidatorException('Data Id is required'); } - $content = $this->createRequest($httpClient, 'DELETE', 'http://'.$this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$data->getServerId()); + $content = $this->createRequest('DELETE', 'http://'.$this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$data->getServerId()); $this->entityManager->remove($data); $this->entityManager->flush(); diff --git a/src/Controller/OgDhcp/Subnet/DeleteHostAction.php b/src/Controller/OgDhcp/Subnet/DeleteHostAction.php index 8b2c251..1dc1a1e 100644 --- a/src/Controller/OgDhcp/Subnet/DeleteHostAction.php +++ b/src/Controller/OgDhcp/Subnet/DeleteHostAction.php @@ -24,7 +24,7 @@ class DeleteHostAction extends AbstractOgDhcpController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function __invoke(Subnet $data, string $clientUuid, HttpClientInterface $httpClient): JsonResponse + public function __invoke(Subnet $data, string $clientUuid): JsonResponse { $client = $this->entityManager->getRepository(Client::class)->findOneBy(['uuid' => $clientUuid]); @@ -42,7 +42,7 @@ class DeleteHostAction extends AbstractOgDhcpController ] ]; - $content = $this->createRequest($httpClient, 'DELETE', 'http://'.$this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$data->getServerId().'/hosts', $params); + $content = $this->createRequest('DELETE', 'http://'.$this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$data->getServerId().'/hosts', $params); $data->removeClient($client); $this->entityManager->persist($data); diff --git a/src/Controller/OgDhcp/Subnet/GetAction.php b/src/Controller/OgDhcp/Subnet/GetAction.php index 257e26b..fcb1cf7 100644 --- a/src/Controller/OgDhcp/Subnet/GetAction.php +++ b/src/Controller/OgDhcp/Subnet/GetAction.php @@ -23,13 +23,13 @@ class GetAction extends AbstractOgDhcpController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function __invoke(Subnet $data, HttpClientInterface $httpClient): JsonResponse + public function __invoke(Subnet $data): JsonResponse { if (!$data->getId()) { throw new ValidatorException('Checksum is required'); } - $content = $this->createRequest($httpClient, 'GET', 'http://'.$this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$data->getServerId()); + $content = $this->createRequest('GET', 'http://'.$this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$data->getServerId()); return new JsonResponse(data: $content, status: Response::HTTP_OK); } diff --git a/src/Controller/OgDhcp/Subnet/GetCollectionAction.php b/src/Controller/OgDhcp/Subnet/GetCollectionAction.php index 95381d0..51fb4d9 100644 --- a/src/Controller/OgDhcp/Subnet/GetCollectionAction.php +++ b/src/Controller/OgDhcp/Subnet/GetCollectionAction.php @@ -21,9 +21,9 @@ class GetCollectionAction extends AbstractOgDhcpController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function __invoke(HttpClientInterface $httpClient): JsonResponse + public function __invoke(): JsonResponse { - $content = $this->createRequest($httpClient, 'GET', 'http://'.$this->ogDhcpApiUrl . '/ogdhcp/v1/subnets'); + $content = $this->createRequest('GET', 'http://'.$this->ogDhcpApiUrl . '/ogdhcp/v1/subnets'); return new JsonResponse(data: $content, status: Response::HTTP_OK); } diff --git a/src/Controller/OgDhcp/Subnet/GetHostsAction.php b/src/Controller/OgDhcp/Subnet/GetHostsAction.php index 8056945..2d553bb 100644 --- a/src/Controller/OgDhcp/Subnet/GetHostsAction.php +++ b/src/Controller/OgDhcp/Subnet/GetHostsAction.php @@ -23,13 +23,13 @@ class GetHostsAction extends AbstractOgDhcpController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function __invoke(Subnet $data, HttpClientInterface $httpClient): JsonResponse + public function __invoke(Subnet $data): JsonResponse { if (!$data->getId()) { throw new ValidatorException('Checksum is required'); } - $content = $this->createRequest($httpClient, 'GET', 'http://'.$this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$data->getServerId().'/hosts'); + $content = $this->createRequest('GET', 'http://'.$this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$data->getServerId().'/hosts'); return new JsonResponse(data: $content, status: Response::HTTP_OK); } diff --git a/src/Controller/OgDhcp/Subnet/PostAction.php b/src/Controller/OgDhcp/Subnet/PostAction.php index 8cc41d1..7d3f6be 100644 --- a/src/Controller/OgDhcp/Subnet/PostAction.php +++ b/src/Controller/OgDhcp/Subnet/PostAction.php @@ -23,11 +23,11 @@ class PostAction extends AbstractOgDhcpController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function __invoke(Subnet $data, HttpClientInterface $httpClient): JsonResponse + public function __invoke(Subnet $data): JsonResponse { $params = [ 'json' => [ - 'subnetId' => $data->getId(), + 'subnetId' => rand(1, 1000), 'mask' => $data->getNetmask(), 'address' => $data->getIpAddress(), 'nextServer' => $data->getNextServer(), @@ -35,7 +35,7 @@ class PostAction extends AbstractOgDhcpController ] ]; - $content = $this->createRequest($httpClient, 'POST', 'http://'.$this->ogDhcpApiUrl.'/ogdhcp/v1/subnets' , $params); + $content = $this->createRequest('POST', 'http://'.$this->ogDhcpApiUrl.'/ogdhcp/v1/subnets' , $params); $data->setServerId($content['message']['id']); $data->setSynchronized(true); diff --git a/src/Controller/OgDhcp/Subnet/PostHostAction.php b/src/Controller/OgDhcp/Subnet/PostHostAction.php index c6e3872..e2f4027 100644 --- a/src/Controller/OgDhcp/Subnet/PostHostAction.php +++ b/src/Controller/OgDhcp/Subnet/PostHostAction.php @@ -27,7 +27,7 @@ class PostHostAction extends AbstractOgDhcpController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function __invoke(SubnetAddHostInput $input, Subnet $subnet, HttpClientInterface $httpClient): JsonResponse + public function __invoke(SubnetAddHostInput $input, Subnet $subnet): JsonResponse { $client = $input->client; @@ -44,7 +44,7 @@ class PostHostAction extends AbstractOgDhcpController 'json' => $data ]; - $content = $this->createRequest($httpClient, 'POST', 'http://'.$this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$subnet->getServerId().'/hosts', $params); + $content = $this->createRequest('POST', 'http://'.$this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$subnet->getServerId().'/hosts', $params); $subnet->addClient($clientEntity); $this->entityManager->persist($subnet); diff --git a/src/Controller/OgDhcp/Subnet/PutAction.php b/src/Controller/OgDhcp/Subnet/PutAction.php index 080f0bc..c7e39b8 100644 --- a/src/Controller/OgDhcp/Subnet/PutAction.php +++ b/src/Controller/OgDhcp/Subnet/PutAction.php @@ -23,7 +23,7 @@ class PutAction extends AbstractOgDhcpController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function __invoke(Subnet $data, HttpClientInterface $httpClient): JsonResponse + public function __invoke(Subnet $data): JsonResponse { if (!$data->getId()) { throw new ValidatorException('Id is required'); @@ -38,7 +38,7 @@ class PutAction extends AbstractOgDhcpController ] ]; - $content = $this->createRequest($httpClient, 'PUT', 'http://'.$this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$data->getServerId(), $params); + $content = $this->createRequest('PUT', 'http://'.$this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$data->getServerId(), $params); $this->entityManager->persist($data); $this->entityManager->flush(); diff --git a/src/Controller/OgDhcp/Subnet/PutHostAction.php b/src/Controller/OgDhcp/Subnet/PutHostAction.php index 5ba614a..cf89d25 100644 --- a/src/Controller/OgDhcp/Subnet/PutHostAction.php +++ b/src/Controller/OgDhcp/Subnet/PutHostAction.php @@ -24,7 +24,7 @@ class PutHostAction extends AbstractOgDhcpController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function __invoke(SubnetAddHostInput $input, Subnet $subnet, HttpClientInterface $httpClient): JsonResponse + public function __invoke(SubnetAddHostInput $input, Subnet $subnet): JsonResponse { $clients = $input->clients; @@ -42,7 +42,7 @@ class PutHostAction extends AbstractOgDhcpController 'json' => $data ]; - $content = $this->createRequest($httpClient, 'PUT', 'http://'.$this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$subnet->getId().'/hosts', $params); + $content = $this->createRequest('PUT', 'http://'.$this->ogDhcpApiUrl.'/ogdhcp/v1/subnets/'.$subnet->getId().'/hosts', $params); } return new JsonResponse(status: Response::HTTP_OK); diff --git a/src/Controller/OgDhcp/Subnet/SyncAction.php b/src/Controller/OgDhcp/Subnet/SyncAction.php index 0c301d7..8b2c945 100644 --- a/src/Controller/OgDhcp/Subnet/SyncAction.php +++ b/src/Controller/OgDhcp/Subnet/SyncAction.php @@ -24,9 +24,9 @@ class SyncAction extends AbstractOgDhcpController * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ - public function __invoke(HttpClientInterface $httpClient, EntityManagerInterface $entityManager): JsonResponse + public function __invoke(EntityManagerInterface $entityManager): JsonResponse { - $content = $this->createRequest($httpClient, 'GET', 'http://'.$this->ogDhcpApiUrl . '/ogdhcp/v1/subnets'); + $content = $this->createRequest('GET', 'http://'.$this->ogDhcpApiUrl . '/ogdhcp/v1/subnets'); $arraySync = []; @@ -63,11 +63,11 @@ class SyncAction extends AbstractOgDhcpController { $getParsedData = $this->getIpAddressAndNetmaskFromCIDRService->__invoke($subnet['subnet']); - $subnetEntity->setName($subnet['boot-file-name']); - $subnetEntity->setBootFileName($subnet['boot-file-name']); + $subnetEntity->setName($subnet['id'].' - '.$subnet['subnet']); + $subnetEntity->setBootFileName($subnet['boot-file-name'] ?? null); $subnetEntity->setIpAddress($getParsedData['ip']); $subnetEntity->setNetmask($getParsedData['mask']); - $subnetEntity->setNextServer($subnet['next-server']); + $subnetEntity->setNextServer($subnet['next-server'] ?? null); foreach ($subnet['reservations'] as $host) { $hostEntity = $this->entityManager->getRepository(Client::class)->findOneBy(['mac' => $host['hw-address']]); diff --git a/src/State/Processor/SubnetProcessor.php b/src/State/Processor/SubnetProcessor.php index 0fef5cf..d8e9fec 100644 --- a/src/State/Processor/SubnetProcessor.php +++ b/src/State/Processor/SubnetProcessor.php @@ -9,16 +9,21 @@ use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Put; use ApiPlatform\State\ProcessorInterface; use ApiPlatform\Validator\ValidatorInterface; +use App\Controller\OgDhcp\Subnet\PostAction; +use App\Controller\OgDhcp\Subnet\PutAction; use App\Dto\Input\SubnetInput; use App\Dto\Output\SubnetOutput; use App\Repository\SubnetRepository; use App\Service\OgBoot\PxeBootFile\PostService; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; readonly class SubnetProcessor implements ProcessorInterface { public function __construct( private SubnetRepository $subnetRepository, - private ValidatorInterface $validator + private ValidatorInterface $validator, + private PostAction $postAction, + private PutAction $putAction, ) { } @@ -40,6 +45,7 @@ readonly class SubnetProcessor implements ProcessorInterface /** * @throws \Exception + * @throws TransportExceptionInterface */ private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): SubnetOutput { @@ -54,6 +60,13 @@ readonly class SubnetProcessor implements ProcessorInterface $subnet = $data->createOrUpdateEntity($entity); $this->validator->validate($subnet); + + if (!$subnet->getId() ) { + $this->postAction->__invoke($subnet); + } else { + $this->putAction->__invoke($subnet); + } + $this->subnetRepository->save($subnet); return new SubnetOutput($subnet); From d3b2da5f1b4db9c83229dc30109cae68ff6020cb Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Mon, 25 Nov 2024 08:28:16 +0100 Subject: [PATCH 4/7] Fixed agent status connection --- src/Controller/OgAgent/StatusAction.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Controller/OgAgent/StatusAction.php b/src/Controller/OgAgent/StatusAction.php index d0492dc..3fcff42 100644 --- a/src/Controller/OgAgent/StatusAction.php +++ b/src/Controller/OgAgent/StatusAction.php @@ -39,6 +39,8 @@ class StatusAction extends AbstractController */ public function __invoke(Client $client): JsonResponse { + $response = null; + if (!$client->getIp()) { throw new ValidatorException('IP is required'); } From 942c967d446bb41ae799bec116fb67b806f80636 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Mon, 25 Nov 2024 09:13:39 +0100 Subject: [PATCH 5/7] Fixed agent status connection --- src/Controller/OgAgent/StatusAction.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controller/OgAgent/StatusAction.php b/src/Controller/OgAgent/StatusAction.php index 3fcff42..056b86f 100644 --- a/src/Controller/OgAgent/StatusAction.php +++ b/src/Controller/OgAgent/StatusAction.php @@ -45,7 +45,7 @@ class StatusAction extends AbstractController throw new ValidatorException('IP is required'); } - if ($client->getStatus() === ClientStatus::OG_LIVE || $client->getStatus() === ClientStatus::OFF) { + if ($client->getStatus() === ClientStatus::OG_LIVE || $client->getStatus() === ClientStatus::OFF || $client->getStatus() === ClientStatus::BUSY) { $response = $this->getOgLiveStatus($client); } From 5c85d687e6cde370596626d59447d786adc7b925 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Mon, 25 Nov 2024 11:53:49 +0100 Subject: [PATCH 6/7] Fixed status when image fail --- src/Controller/OgAgent/Webhook/ClientsController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Controller/OgAgent/Webhook/ClientsController.php b/src/Controller/OgAgent/Webhook/ClientsController.php index 2ceb9ee..112e461 100644 --- a/src/Controller/OgAgent/Webhook/ClientsController.php +++ b/src/Controller/OgAgent/Webhook/ClientsController.php @@ -79,6 +79,7 @@ class ClientsController extends AbstractController $trace->setFinishedAt(new \DateTime()); $trace->setOutput($data['der']); $image->setCreated(false); + $image->setStatus(ImageStatus::FAILED); } $this->entityManager->persist($image); From 48b7225c0168b569d7037e70e9db76b9b6efe6b9 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Mon, 25 Nov 2024 20:06:09 +0100 Subject: [PATCH 7/7] Added monolog. Updated agent webhook --- composer.json | 1 + composer.lock | 269 +++++++++++++++++- config/bundles.php | 1 + config/packages/monolog.yaml | 62 ++++ src/Controller/OgAgent/StatusAction.php | 4 +- .../OgAgent/Webhook/ClientsController.php | 52 ++-- symfony.lock | 12 + 7 files changed, 380 insertions(+), 21 deletions(-) create mode 100644 config/packages/monolog.yaml diff --git a/composer.json b/composer.json index b7550df..9d05bf0 100644 --- a/composer.json +++ b/composer.json @@ -27,6 +27,7 @@ "symfony/flex": "^2", "symfony/framework-bundle": "6.4.*", "symfony/http-client": "6.4.*", + "symfony/monolog-bundle": "^3.10", "symfony/property-access": "6.4.*", "symfony/property-info": "6.4.*", "symfony/runtime": "6.4.*", diff --git a/composer.lock b/composer.lock index 2bfe6d3..abefe8a 100644 --- a/composer.lock +++ b/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": "aaa904068da3e39927da2e6658330011", + "content-hash": "2df97d4a1797242acadb47d83b3fbe98", "packages": [ { "name": "api-platform/core", @@ -2091,6 +2091,109 @@ ], "time": "2024-07-03T20:49:59+00:00" }, + { + "name": "monolog/monolog", + "version": "3.8.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "32e515fdc02cdafbe4593e30a9350d486b125b67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/32e515fdc02cdafbe4593e30a9350d486b125b67", + "reference": "32e515fdc02cdafbe4593e30a9350d486b125b67", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", + "predis/predis": "^1.1 || ^2", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/3.8.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2024-11-12T13:57:08+00:00" + }, { "name": "nelmio/cors-bundle", "version": "2.5.0", @@ -4840,6 +4943,166 @@ ], "time": "2024-07-26T14:52:04+00:00" }, + { + "name": "symfony/monolog-bridge", + "version": "v6.4.13", + "source": { + "type": "git", + "url": "https://github.com/symfony/monolog-bridge.git", + "reference": "9d14621e59f22c2b6d030d92d37ffe5ae1e60452" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/9d14621e59f22c2b6d030d92d37ffe5ae1e60452", + "reference": "9d14621e59f22c2b6d030d92d37ffe5ae1e60452", + "shasum": "" + }, + "require": { + "monolog/monolog": "^1.25.1|^2|^3", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "symfony/console": "<5.4", + "symfony/http-foundation": "<5.4", + "symfony/security-core": "<5.4" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/mailer": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/mime": "^5.4|^6.0|^7.0", + "symfony/security-core": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Monolog\\": "" + }, + "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 integration for Monolog with various Symfony components", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/monolog-bridge/tree/v6.4.13" + }, + "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": "2024-10-14T08:49:08+00:00" + }, + { + "name": "symfony/monolog-bundle", + "version": "v3.10.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/monolog-bundle.git", + "reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181", + "reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181", + "shasum": "" + }, + "require": { + "monolog/monolog": "^1.25.1 || ^2.0 || ^3.0", + "php": ">=7.2.5", + "symfony/config": "^5.4 || ^6.0 || ^7.0", + "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", + "symfony/http-kernel": "^5.4 || ^6.0 || ^7.0", + "symfony/monolog-bridge": "^5.4 || ^6.0 || ^7.0" + }, + "require-dev": { + "symfony/console": "^5.4 || ^6.0 || ^7.0", + "symfony/phpunit-bridge": "^6.3 || ^7.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + }, + "type": "symfony-bundle", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bundle\\MonologBundle\\": "" + }, + "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": "Symfony MonologBundle", + "homepage": "https://symfony.com", + "keywords": [ + "log", + "logging" + ], + "support": { + "issues": "https://github.com/symfony/monolog-bundle/issues", + "source": "https://github.com/symfony/monolog-bundle/tree/v3.10.0" + }, + "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": "2023-11-06T17:08:13+00:00" + }, { "name": "symfony/password-hasher", "version": "v6.4.8", @@ -9976,7 +10239,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { @@ -9984,6 +10247,6 @@ "ext-ctype": "*", "ext-iconv": "*" }, - "platform-dev": [], + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/config/bundles.php b/config/bundles.php index 826d993..f1a3820 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -16,4 +16,5 @@ return [ Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], Stof\DoctrineExtensionsBundle\StofDoctrineExtensionsBundle::class => ['all' => true], DAMA\DoctrineTestBundle\DAMADoctrineTestBundle::class => ['test' => true], + Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], ]; diff --git a/config/packages/monolog.yaml b/config/packages/monolog.yaml new file mode 100644 index 0000000..9db7d8a --- /dev/null +++ b/config/packages/monolog.yaml @@ -0,0 +1,62 @@ +monolog: + channels: + - deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists + +when@dev: + monolog: + handlers: + main: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.log" + level: debug + channels: ["!event"] + # uncomment to get logging in your browser + # you may have to allow bigger header sizes in your Web server configuration + #firephp: + # type: firephp + # level: info + #chromephp: + # type: chromephp + # level: info + console: + type: console + process_psr_3_messages: false + channels: ["!event", "!doctrine", "!console"] + +when@test: + monolog: + handlers: + main: + type: fingers_crossed + action_level: error + handler: nested + excluded_http_codes: [404, 405] + channels: ["!event"] + nested: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.log" + level: debug + +when@prod: + monolog: + handlers: + main: + type: fingers_crossed + action_level: error + handler: nested + excluded_http_codes: [404, 405] + buffer_size: 50 # How many messages should be saved? Prevent memory leaks + nested: + type: stream + path: php://stderr + level: debug + formatter: monolog.formatter.json + console: + type: console + process_psr_3_messages: false + channels: ["!event", "!doctrine"] + deprecation: + type: stream + channels: [deprecation] + path: php://stderr + formatter: monolog.formatter.json diff --git a/src/Controller/OgAgent/StatusAction.php b/src/Controller/OgAgent/StatusAction.php index 056b86f..5ce9d66 100644 --- a/src/Controller/OgAgent/StatusAction.php +++ b/src/Controller/OgAgent/StatusAction.php @@ -59,7 +59,7 @@ class StatusAction extends AbstractController ); } - public function getOgLiveStatus (Client $client): JsonResponse|int + public function getOgLiveStatus (Client $client): JsonResponse|int|string { try { $response = $this->httpClient->request('POST', 'https://' . $client->getIp() . ':8000/ogAdmClient/status', [ @@ -77,7 +77,7 @@ class StatusAction extends AbstractController } catch (TransportExceptionInterface $e) { $client->setStatus(ClientStatus::OFF); - return Response::HTTP_INTERNAL_SERVER_ERROR; + return $e->getMessage(); } $data = json_decode($response->getContent(), true); diff --git a/src/Controller/OgAgent/Webhook/ClientsController.php b/src/Controller/OgAgent/Webhook/ClientsController.php index 112e461..e3a4f4c 100644 --- a/src/Controller/OgAgent/Webhook/ClientsController.php +++ b/src/Controller/OgAgent/Webhook/ClientsController.php @@ -10,11 +10,14 @@ use App\Entity\Software; use App\Entity\SoftwareProfile; use App\Entity\Trace; use App\Model\ClientStatus; +use App\Model\CommandTypes; use App\Model\ImageStatus; use App\Model\SoftwareTypes; use App\Model\TraceStatus; use App\Service\CreatePartitionService; +use App\Service\Trace\CreateService; use Doctrine\ORM\EntityManagerInterface; +use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; @@ -33,7 +36,9 @@ class ClientsController extends AbstractController public function __construct( protected readonly EntityManagerInterface $entityManager, public readonly CreateAuxFilesAction $createAuxFilesAction, - protected readonly CreatePartitionService $createPartitionService + protected readonly CreatePartitionService $createPartitionService, + protected readonly LoggerInterface $logger, + protected readonly CreateService $createService, ) { } @@ -56,38 +61,51 @@ class ClientsController extends AbstractController } } + $this->logger->info('Webhook data received', $data); + if ($data['nfn'] === 'RESPUESTA_CrearImagen') { $trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]); $image = $this->entityManager->getRepository(Image::class)->findOneBy(['uuid' => $data['idi']]); if (!$image) { + $this->logger->error('Image not found', $data); return new JsonResponse(['message' => 'Image not found'], Response::HTTP_NOT_FOUND); } + if (!$trace) { + $this->logger->error('Trace not found', $data); + return new JsonResponse(['message' => 'Trace not found'], Response::HTTP_NOT_FOUND); + } + if ($data['res'] === 1) { $trace->setStatus(TraceStatus::SUCCESS); $trace->setFinishedAt(new \DateTime()); $image->setStatus(ImageStatus::AUX_FILES_PENDING); $image->setCreated(true); + $this->logger->info('Start partition creation. ', ['image' => (string) $image->getUuid()]); if (isset($data['cfg'])) { $this->createPartitionService->__invoke($data, $image->getClient()); } + $this->logger->info('Starting software profile creation. ', ['image' => (string) $image->getUuid()]); $this->createSoftwareProfile($data['inv_sft'], $image); + $this->logger->info('Start aux files ogrepo API ', ['image' => (string) $image->getUuid()]); $this->createAuxFilesAction->__invoke($image); + $this->logger->info('End aux files ogrepo API ', ['image' => (string) $image->getUuid()]); } else { $trace->setStatus(TraceStatus::FAILED); $trace->setFinishedAt(new \DateTime()); $trace->setOutput($data['der']); $image->setCreated(false); $image->setStatus(ImageStatus::FAILED); + $this->logger->error('Image updated failed', $data); } - $this->entityManager->persist($image); + $this->entityManager->persist($image); $client = $trace->getClient(); $client->setStatus(ClientStatus::OG_LIVE); - $this->entityManager->persist($trace); $this->entityManager->flush(); + $this->logger->info('Image updated. Success.', ['image' => (string) $image->getUuid()]); } if ($data['nfn'] === 'RESPUESTA_RestaurarImagen') { @@ -112,26 +130,28 @@ class ClientsController extends AbstractController return new JsonResponse([], Response::HTTP_OK); } - public function createSoftwareProfile (string $base64Data, Image $image): void + public function createSoftwareProfile(string $base64Data, Image $image): void { $decodedData = base64_decode($base64Data); + $this->logger->info('Software profile decoded', ['data' => '']); + $softwareList = array_map('trim', explode(",", $decodedData)); + $softwareList = array_filter($softwareList); + $existingSoftware = $this->entityManager->getRepository(Software::class)->findBy(['name' => $softwareList]); + $existingNames = array_map(fn($software) => $software->getName(), $existingSoftware); + $newSoftwareNames = array_diff($softwareList, $existingNames); - $softwareList = explode("\n", $decodedData); + foreach ($newSoftwareNames as $software) { + $softwareEntity = new Software(); + $softwareEntity->setName($software); + $softwareEntity->setType(SoftwareTypes::APPLICATION); + $this->entityManager->persist($softwareEntity); + } $softwareProfile = new SoftwareProfile(); - $softwareProfile->setDescription('Perfil : '.$image->getName()); + $softwareProfile->setDescription('Perfil: ' . $image->getName()); $softwareProfile->setOrganizationalUnit($image->getClient()->getOrganizationalUnit()); - foreach ($softwareList as $software) { - $software = trim($software); - $softwareEntity = $this->entityManager->getRepository(Software::class)->findOneBy(['name' => $software]); - if (!$softwareEntity) { - $softwareEntity = new Software(); - $softwareEntity->setName($software); - $softwareEntity->setType(SoftwareTypes::APPLICATION); - $this->entityManager->persist($softwareEntity); - } - + foreach ($existingSoftware as $softwareEntity) { $softwareEntity->addSoftwareProfile($softwareProfile); } diff --git a/symfony.lock b/symfony.lock index caba1f7..c537b54 100644 --- a/symfony.lock +++ b/symfony.lock @@ -178,6 +178,18 @@ "ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f" } }, + "symfony/monolog-bundle": { + "version": "3.10", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "3.7", + "ref": "aff23899c4440dd995907613c1dd709b6f59503f" + }, + "files": [ + "config/packages/monolog.yaml" + ] + }, "symfony/phpunit-bridge": { "version": "7.1", "recipe": {