From ca3e547b564d24089a39dc5ebc842c51a05afb16 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Mon, 17 Feb 2025 09:13:48 +0100 Subject: [PATCH] Some improvements. Added new filters --- migrations/Version20250214114518.php | 31 +++++++++++++++++++ migrations/Version20250214120305.php | 31 +++++++++++++++++++ migrations/Version20250214121437.php | 31 +++++++++++++++++++ .../OgBoot/AbstractOgBootController.php | 16 ++++++---- .../OgBoot/OgLive/GetIsosAction.php | 22 +++++++++++-- .../OgBoot/OgLive/InstallAction.php | 11 +++++++ src/Controller/OgBoot/OgLive/SyncAction.php | 3 ++ .../Webhook/InstallOgLiveResponseAction.php | 23 ++++++++++++-- src/Dto/Input/OgLiveInput.php | 1 + src/Dto/Output/OgLiveOutput.php | 8 +++++ src/Dto/Output/TraceOutput.php | 8 +++-- src/Entity/OgLive.php | 17 ++++++++++ src/Entity/Trace.php | 2 +- src/Factory/OgLiveFactory.php | 1 + src/Model/CommandTypes.php | 4 +++ src/Service/Trace/CreateService.php | 2 +- .../ExtractOgLiveFilenameDateService.php | 15 +++++++++ .../Utils/SymflipyOgLiveFilenameService.php | 15 +++++++++ 18 files changed, 227 insertions(+), 14 deletions(-) create mode 100644 migrations/Version20250214114518.php create mode 100644 migrations/Version20250214120305.php create mode 100644 migrations/Version20250214121437.php create mode 100644 src/Service/Utils/ExtractOgLiveFilenameDateService.php create mode 100644 src/Service/Utils/SymflipyOgLiveFilenameService.php diff --git a/migrations/Version20250214114518.php b/migrations/Version20250214114518.php new file mode 100644 index 0000000..76b5fba --- /dev/null +++ b/migrations/Version20250214114518.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE og_live ADD date DATETIME NOT NULL, ADD name VARCHAR(255) NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE og_live DROP date, DROP name'); + } +} diff --git a/migrations/Version20250214120305.php b/migrations/Version20250214120305.php new file mode 100644 index 0000000..608297d --- /dev/null +++ b/migrations/Version20250214120305.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE trace CHANGE client_id client_id INT DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE trace CHANGE client_id client_id INT NOT NULL'); + } +} diff --git a/migrations/Version20250214121437.php b/migrations/Version20250214121437.php new file mode 100644 index 0000000..e2959bd --- /dev/null +++ b/migrations/Version20250214121437.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE og_live CHANGE date date DATETIME DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE og_live CHANGE date date DATETIME NOT NULL'); + } +} diff --git a/src/Controller/OgBoot/AbstractOgBootController.php b/src/Controller/OgBoot/AbstractOgBootController.php index 2ea3d77..d39cfd7 100644 --- a/src/Controller/OgBoot/AbstractOgBootController.php +++ b/src/Controller/OgBoot/AbstractOgBootController.php @@ -6,6 +6,8 @@ namespace App\Controller\OgBoot; use App\Controller\OgBoot\PxeBootFile\PostAction; use App\Service\Trace\CreateService; +use App\Service\Utils\ExtractOgLiveFilenameDateService; +use App\Service\Utils\SymflipyOgLiveFilenameService; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\DependencyInjection\Attribute\Autowire; @@ -24,14 +26,16 @@ abstract class AbstractOgBootController extends AbstractController { public function __construct( #[Autowire(env: 'OG_BOOT_API_URL')] - protected string $ogBootApiUrl, + protected string $ogBootApiUrl, #[Autowire(env: 'OG_CORE_IP')] - protected string $ogCoreIP, + protected string $ogCoreIP, #[Autowire(env: 'OG_LOG_IP')] - protected string $ogLogIp, - protected readonly EntityManagerInterface $entityManager, - protected readonly HttpClientInterface $httpClient, - protected readonly CreateService $createService, + protected string $ogLogIp, + protected readonly EntityManagerInterface $entityManager, + protected readonly HttpClientInterface $httpClient, + protected readonly CreateService $createService, + protected readonly SymflipyOgLiveFilenameService $symflipyOgLiveFilenameService, + protected readonly ExtractOgLiveFilenameDateService $extractOgLiveFilenameDateService, ) { } diff --git a/src/Controller/OgBoot/OgLive/GetIsosAction.php b/src/Controller/OgBoot/OgLive/GetIsosAction.php index 80b212b..d284859 100644 --- a/src/Controller/OgBoot/OgLive/GetIsosAction.php +++ b/src/Controller/OgBoot/OgLive/GetIsosAction.php @@ -25,6 +25,24 @@ class GetIsosAction extends AbstractOgBootController { $content = $this->createRequest('GET', 'http://'.$this->ogBootApiUrl.'/ogboot/v1/oglives/isos'); - return new JsonResponse(data: $content, status: Response::HTTP_OK); + if (!isset($content['message']) || !is_array($content['message'])) { + return new JsonResponse(data: ['error' => 'Invalid response'], status: Response::HTTP_BAD_REQUEST); + } + + $isos = array_map(function ($iso) { + $filename = $this->symflipyOgLiveFilenameService->__invoke($iso['filename']); + + return [ + 'id' => $iso['id'], + 'filename' => $filename, + 'url' => $iso['url'], + 'installed' => $iso['installed'], + 'compatible' => $iso['compatible'], + ]; + }, $content['message']); + + usort($isos, fn($a, $b) => $b['id'] <=> $a['id']); + + return new JsonResponse(data: ['success' => 'ISOs retrieved successfully', 'message' => $isos], status: Response::HTTP_OK); } -} \ No newline at end of file +} diff --git a/src/Controller/OgBoot/OgLive/InstallAction.php b/src/Controller/OgBoot/OgLive/InstallAction.php index e0d6be6..bbc1e06 100644 --- a/src/Controller/OgBoot/OgLive/InstallAction.php +++ b/src/Controller/OgBoot/OgLive/InstallAction.php @@ -4,7 +4,9 @@ namespace App\Controller\OgBoot\OgLive; use App\Controller\OgBoot\AbstractOgBootController; use App\Entity\OgLive; +use App\Model\CommandTypes; use App\Model\OgLiveStatus; +use App\Model\TraceStatus; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Response; @@ -38,8 +40,17 @@ class InstallAction extends AbstractOgBootController ] ]; + $inputData= [ + 'downloadUrl' => $data->getDownloadUrl(), + 'uuid' => 'InstallOgLive_'.$data->getUuid() + ]; + $content = $this->createRequest('POST', 'http://'.$this->ogBootApiUrl.'/ogboot/v1/oglives/install', $params); + $this->createService->__invoke(null, CommandTypes::INSTALL_OGLIVE, TraceStatus::IN_PROGRESS, 'InstallOgLive_'.$data->getUuid(), $inputData); + + $data->setName($this->symflipyOgLiveFilenameService->__invoke($data->getFilename())); + $data->setDate(new \DateTime()); $data->setStatus(OgLiveStatus::PENDING); $this->entityManager->persist($data); $this->entityManager->flush(); diff --git a/src/Controller/OgBoot/OgLive/SyncAction.php b/src/Controller/OgBoot/OgLive/SyncAction.php index 9cc2a43..286f1b8 100644 --- a/src/Controller/OgBoot/OgLive/SyncAction.php +++ b/src/Controller/OgBoot/OgLive/SyncAction.php @@ -56,9 +56,12 @@ class SyncAction extends AbstractOgBootController * @param OgLive|null $ogLiveEntity * @param mixed $ogLive * @return void + * @throws \Exception */ private function extracted(OgLive $ogLiveEntity, mixed $ogLive): void { + $ogLiveEntity->setName($this->symflipyOgLiveFilenameService->__invoke(str_replace(self::OG_BOOT_DIRECTORY, '', $ogLive['directory']))); + $ogLiveEntity->setDate(new \DateTime($this->extractOgLiveFilenameDateService->__invoke(str_replace(self::OG_BOOT_DIRECTORY, '', $ogLive['directory'])))); $ogLiveEntity->setInstalled(true); $ogLiveEntity->setArchitecture($ogLive['architecture']); $ogLiveEntity->setDistribution($ogLive['distribution']); diff --git a/src/Controller/OgBoot/OgLive/Webhook/InstallOgLiveResponseAction.php b/src/Controller/OgBoot/OgLive/Webhook/InstallOgLiveResponseAction.php index f437848..5a12077 100644 --- a/src/Controller/OgBoot/OgLive/Webhook/InstallOgLiveResponseAction.php +++ b/src/Controller/OgBoot/OgLive/Webhook/InstallOgLiveResponseAction.php @@ -4,7 +4,10 @@ namespace App\Controller\OgBoot\OgLive\Webhook; use App\Controller\OgBoot\AbstractOgBootController; use App\Entity\OgLive; +use App\Entity\Trace; use App\Model\OgLiveStatus; +use App\Service\Utils\ExtractOgLiveFilenameDateService; +use App\Service\Utils\SymflipyOgLiveFilenameService; use Doctrine\ORM\EntityManagerInterface; use Psr\Log\LoggerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -28,12 +31,17 @@ class InstallOgLiveResponseAction extends AbstractController const string OG_BOOT_DIRECTORY = '/opt/opengnsys/ogboot/tftpboot//'; public function __construct( - protected readonly EntityManagerInterface $entityManager, - protected readonly LoggerInterface $logger, + protected readonly EntityManagerInterface $entityManager, + protected readonly LoggerInterface $logger, + protected readonly SymflipyOgLiveFilenameService $symflipyOgLiveFilenameService, + protected readonly ExtractOgLiveFilenameDateService $extractOgLiveFilenameDateService, ) { } + /** + * @throws \Exception + */ #[Route('/og-lives/install/webhook', name: 'install_webhook', methods: ['POST'])] public function installWebhook(Request $request): JsonResponse { @@ -54,11 +62,17 @@ class InstallOgLiveResponseAction extends AbstractController $status = $data['status']; $ogLive = $this->entityManager->getRepository(OgLive::class)->findOneBy(['uuid' => $ogCoreId]); + $trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => 'InstallOgLive_'.$ogCoreId]); if (!$ogLive) { return new JsonResponse(['error' => 'OgLive not found'], Response::HTTP_NOT_FOUND); } + if ($trace) { + $trace->setStatus($status === self::OG_LIVE_INSTALL_SUCCESS ? 'success' : 'failure'); + $this->entityManager->persist($trace); + } + if ($ogLive->getStatus() === OgLiveStatus::ACTIVE) { return new JsonResponse(['error' => 'OgLive is already active'], Response::HTTP_BAD_REQUEST); } @@ -69,9 +83,14 @@ class InstallOgLiveResponseAction extends AbstractController return new JsonResponse(data: sprintf('OgLive %s updated successfully', $ogLive->getChecksum()), status: Response::HTTP_OK); } + /** + * @throws \Exception + */ private function updateOgLive (OgLive $ogLive, array $details, string $status): void { if ($status === self::OG_LIVE_INSTALL_SUCCESS) { + $ogLive->setName($this->symflipyOgLiveFilenameService->__invoke($details['filename'])); + $ogLive->setDate(new \DateTime($this->extractOgLiveFilenameDateService->__invoke($details['filename']))); $ogLive->setFilename(str_replace(self::OG_BOOT_DIRECTORY, '', $ogLive['directory'])); $ogLive->setInstalled(true); $ogLive->setSynchronized(true); diff --git a/src/Dto/Input/OgLiveInput.php b/src/Dto/Input/OgLiveInput.php index ff75678..2646088 100644 --- a/src/Dto/Input/OgLiveInput.php +++ b/src/Dto/Input/OgLiveInput.php @@ -37,6 +37,7 @@ final class OgLiveInput $filename = substr($filename, 0, -4); } + $ogLive->setName($filename); $ogLive->setFilename($filename); $ogLive->setDownloadUrl($this->downloadUrl); $ogLive->setStatus(OgLiveStatus::INACTIVE); diff --git a/src/Dto/Output/OgLiveOutput.php b/src/Dto/Output/OgLiveOutput.php index 1068846..5e636bd 100644 --- a/src/Dto/Output/OgLiveOutput.php +++ b/src/Dto/Output/OgLiveOutput.php @@ -10,6 +10,9 @@ use Symfony\Component\Serializer\Annotation\Groups; #[Get(shortName: 'OgLive')] final class OgLiveOutput extends AbstractOutput { + #[Groups(['og-live:read', 'client:read', "organizational-unit:read"])] + public ?string $name = ''; + #[Groups(['og-live:read'])] public ?bool $synchronized = false; @@ -46,6 +49,9 @@ final class OgLiveOutput extends AbstractOutput #[Groups(['og-live:read'])] public \DateTime $createdAt; + #[Groups(['og-live:read', 'client:read', "organizational-unit:read"])] + public ?\DateTimeInterface $date; + #[Groups(['og-live:read'])] public ?string $createdBy = null; @@ -53,6 +59,7 @@ final class OgLiveOutput extends AbstractOutput { parent::__construct($ogLive); + $this->name = $ogLive->getName(); $this->synchronized = $ogLive->isSynchronized(); $this->installed = $ogLive->isInstalled(); $this->isDefault = $ogLive->getIsDefault(); @@ -64,6 +71,7 @@ final class OgLiveOutput extends AbstractOutput $this->kernel = $ogLive->getKernel(); $this->architecture = $ogLive->getArchitecture(); $this->status = $ogLive->getStatus(); + $this->date = $ogLive->getDate(); $this->createdAt = $ogLive->getCreatedAt(); $this->createdBy = $ogLive->getCreatedBy(); } diff --git a/src/Dto/Output/TraceOutput.php b/src/Dto/Output/TraceOutput.php index 8bbc100..c4666a3 100644 --- a/src/Dto/Output/TraceOutput.php +++ b/src/Dto/Output/TraceOutput.php @@ -14,7 +14,7 @@ final class TraceOutput extends AbstractOutput public ?string $command; #[Groups(['trace:read'])] - public ClientOutput $client; + public ?ClientOutput $client = null; #[Groups(['trace:read'])] public string $status; @@ -45,7 +45,11 @@ final class TraceOutput extends AbstractOutput parent::__construct($trace); $this->command = $trace->getCommand(); - $this->client = new ClientOutput($trace->getClient()); + + if ($trace->getClient() !== null) { + $this->client = new ClientOutput($trace->getClient()); + } + $this->status = $trace->getStatus(); $this->jobId = $trace->getJobId(); $this->executedAt = $trace->getExecutedAt(); diff --git a/src/Entity/OgLive.php b/src/Entity/OgLive.php index 4e01da1..f6f5e3a 100644 --- a/src/Entity/OgLive.php +++ b/src/Entity/OgLive.php @@ -5,6 +5,7 @@ namespace App\Entity; use App\Repository\OgLiveRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; @@ -13,6 +14,7 @@ use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; #[UniqueEntity(fields: ['filename'], message: 'validators.og_live.filename.unique')] class OgLive extends AbstractEntity { + use NameableTrait; use SynchronizedTrait; #[ORM\Column(length: 255, nullable: true)] @@ -54,6 +56,9 @@ class OgLive extends AbstractEntity #[ORM\Column(length: 255)] private ?string $status = null; + #[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)] + private ?\DateTimeInterface $date = null; + public function __construct() { parent::__construct(); @@ -219,4 +224,16 @@ class OgLive extends AbstractEntity return $this; } + + public function getDate(): ?\DateTimeInterface + { + return $this->date; + } + + public function setDate(?\DateTimeInterface $date): static + { + $this->date = $date; + + return $this; + } } diff --git a/src/Entity/Trace.php b/src/Entity/Trace.php index 97c3588..0faf0c7 100644 --- a/src/Entity/Trace.php +++ b/src/Entity/Trace.php @@ -10,7 +10,7 @@ use Doctrine\ORM\Mapping as ORM; class Trace extends AbstractEntity { #[ORM\ManyToOne(inversedBy: 'traces')] - #[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')] + #[ORM\JoinColumn(nullable: true, onDelete: 'CASCADE')] private ?Client $client = null; #[ORM\Column(length: 255, nullable: true)] diff --git a/src/Factory/OgLiveFactory.php b/src/Factory/OgLiveFactory.php index 2faad27..59f55cd 100644 --- a/src/Factory/OgLiveFactory.php +++ b/src/Factory/OgLiveFactory.php @@ -33,6 +33,7 @@ final class OgLiveFactory extends ModelFactory protected function getDefaults(): array { return [ + 'name' => self::faker()->text(255), 'createdAt' => self::faker()->dateTime(), 'filename' => self::faker()->text(255), 'status' => OgLiveStatus::ACTIVE, diff --git a/src/Model/CommandTypes.php b/src/Model/CommandTypes.php index 79086c4..b8b3cbf 100644 --- a/src/Model/CommandTypes.php +++ b/src/Model/CommandTypes.php @@ -18,6 +18,8 @@ final class CommandTypes public const string LOGOUT = 'logout'; public const string PARTITION_AND_FORMAT = 'partition-and-format'; + public const string INSTALL_OGLIVE = 'install-oglive'; + private const array COMMAND_TYPES = [ self::DEPLOY_IMAGE => 'Deploy Image', self::RESTORE_IMAGE => 'Update Cache', @@ -31,6 +33,8 @@ final class CommandTypes self::LOGIN => 'Login', self::LOGOUT => 'Logout', self::PARTITION_AND_FORMAT => 'Partition and Format', + self::TRANSFER_IMAGE => 'Transfer Image', + self::INSTALL_OGLIVE => 'Instalar OgLive', ]; public static function getCommandTypes(): array diff --git a/src/Service/Trace/CreateService.php b/src/Service/Trace/CreateService.php index 07a6de1..d22d83d 100644 --- a/src/Service/Trace/CreateService.php +++ b/src/Service/Trace/CreateService.php @@ -15,7 +15,7 @@ readonly class CreateService { } - public function __invoke(Client $client, ?string $command, string $status, ?string $jobId = '', ?array $input = []): Trace + public function __invoke(?Client $client = null, ?string $command, string $status, ?string $jobId = '', ?array $input = []): Trace { $trace = new Trace(); $trace->setClient($client); diff --git a/src/Service/Utils/ExtractOgLiveFilenameDateService.php b/src/Service/Utils/ExtractOgLiveFilenameDateService.php new file mode 100644 index 0000000..4b2278c --- /dev/null +++ b/src/Service/Utils/ExtractOgLiveFilenameDateService.php @@ -0,0 +1,15 @@ +