Compare commits
8 Commits
5e143e08a9
...
69bbf3e209
Author | SHA1 | Date |
---|---|---|
|
69bbf3e209 | |
|
966936c4f2 | |
|
2588dd07f2 | |
|
21cd73bee2 | |
|
7b74c9ab70 | |
|
e325578e2b | |
|
e51e1e13ea | |
|
af5ad81199 |
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -1,4 +1,15 @@
|
|||
# Changelog
|
||||
## [0.15.0] - 2025-06-26
|
||||
### Added
|
||||
- Se ha añadido la integracion con ogGit para la gestion de imagenes.
|
||||
- Se ha añadido la primera parte del sistema de cola de acciones.
|
||||
- Integracion con el endpoint del agente KillJob
|
||||
- Posibilidad de poder vaciar la cola de acciones.
|
||||
|
||||
### Fixed
|
||||
- Se ha corregido un bug que hacia que al mover clientes entre aulas, diera error en caso de que el cliente no tuviera PXE asignado.
|
||||
|
||||
---
|
||||
## [0.14.2] - 2025-06-09
|
||||
### Improved
|
||||
- Cambio en el template base del menu. Ahora apunta a los script de python de manera correcta.
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
resources:
|
||||
App\Entity\GitImageRepository:
|
||||
processor: App\State\Processor\GitImageRepositoryProcessor
|
||||
input: App\Dto\Input\GitImageRepositoryInput
|
||||
output: App\Dto\Output\GitImageRepositoryOutput
|
||||
normalizationContext:
|
||||
groups: ['default', 'git-image-repository:read']
|
||||
denormalizationContext:
|
||||
groups: ['git-image-repository:write']
|
||||
operations:
|
||||
ApiPlatform\Metadata\GetCollection:
|
||||
provider: App\State\Provider\GitImageRepositoryProvider
|
||||
filters:
|
||||
- 'api_platform.filter.image_image_repository.order'
|
||||
- 'api_platform.filter.image_image_repository.search'
|
||||
|
||||
ApiPlatform\Metadata\Get:
|
||||
provider: App\State\Provider\GitImageRepositoryProvider
|
||||
ApiPlatform\Metadata\Put:
|
||||
provider: App\State\Provider\GitImageRepositoryProvider
|
||||
ApiPlatform\Metadata\Patch:
|
||||
provider: App\State\Provider\GitImageRepositoryProvider
|
||||
ApiPlatform\Metadata\Post: ~
|
||||
ApiPlatform\Metadata\Delete: ~
|
||||
|
||||
get_image_ogrepository:
|
||||
shortName: OgRepository Server
|
||||
description: Get image in OgRepository
|
||||
class: ApiPlatform\Metadata\Get
|
||||
method: GET
|
||||
input: false
|
||||
uriTemplate: /image-image-repositories/server/{uuid}/get
|
||||
controller: App\Controller\OgRepository\Image\GetAction
|
||||
|
||||
get_image_tags:
|
||||
shortName: OgRepository Server
|
||||
description: Get image tags in OgRepository
|
||||
class: ApiPlatform\Metadata\Get
|
||||
method: GET
|
||||
input: false
|
||||
uriTemplate: /git-image-repositories/server/{uuid}/get-tags
|
||||
controller: App\Controller\OgRepository\Git\GetTagsAction
|
||||
|
||||
|
||||
properties:
|
||||
App\Entity\GitImageRepository:
|
||||
id:
|
||||
identifier: false
|
||||
uuid:
|
||||
identifier: true
|
|
@ -0,0 +1,109 @@
|
|||
resources:
|
||||
App\Entity\GitRepository:
|
||||
processor: App\State\Processor\GitRepositoryProcessor
|
||||
input: App\Dto\Input\GitRepositoryInput
|
||||
output: App\Dto\Output\GitRepositoryOutput
|
||||
normalizationContext:
|
||||
groups: ['default', 'git-repository:read']
|
||||
denormalizationContext:
|
||||
groups: ['git-repository:write']
|
||||
operations:
|
||||
ApiPlatform\Metadata\GetCollection:
|
||||
provider: App\State\Provider\GitRepositoryProvider
|
||||
filters:
|
||||
- 'api_platform.filter.git_repository.order'
|
||||
- 'api_platform.filter.git_repository.search'
|
||||
openapiContext:
|
||||
summary: 'Obtener lista de repositorios Git'
|
||||
description: 'Obtiene todos los repositorios Git de un servidor específico'
|
||||
parameters:
|
||||
- name: 'repository'
|
||||
in: 'query'
|
||||
required: true
|
||||
schema:
|
||||
type: 'integer'
|
||||
description: 'ID del ImageRepository que contiene los repositorios'
|
||||
- name: 'page'
|
||||
in: 'query'
|
||||
schema:
|
||||
type: 'integer'
|
||||
default: 1
|
||||
description: 'Número de página'
|
||||
- name: 'limit'
|
||||
in: 'query'
|
||||
schema:
|
||||
type: 'integer'
|
||||
default: 10
|
||||
description: 'Elementos por página'
|
||||
|
||||
ApiPlatform\Metadata\Get:
|
||||
provider: App\State\Provider\GitRepositoryProvider
|
||||
openapiContext:
|
||||
summary: 'Obtener un repositorio Git específico'
|
||||
description: 'Obtiene un repositorio Git específico por su nombre'
|
||||
parameters:
|
||||
- name: 'repository'
|
||||
in: 'query'
|
||||
required: true
|
||||
schema:
|
||||
type: 'integer'
|
||||
description: 'ID del ImageRepository'
|
||||
|
||||
ApiPlatform\Metadata\Put:
|
||||
provider: App\State\Provider\GitRepositoryProvider
|
||||
openapiContext:
|
||||
summary: 'Actualizar un repositorio Git'
|
||||
description: 'Actualiza un repositorio Git existente en el servidor externo'
|
||||
parameters:
|
||||
- name: 'repository'
|
||||
in: 'query'
|
||||
required: true
|
||||
schema:
|
||||
type: 'integer'
|
||||
description: 'ID del ImageRepository'
|
||||
|
||||
ApiPlatform\Metadata\Patch:
|
||||
provider: App\State\Provider\GitRepositoryProvider
|
||||
openapiContext:
|
||||
summary: 'Actualizar parcialmente un repositorio Git'
|
||||
description: 'Actualiza parcialmente un repositorio Git existente'
|
||||
parameters:
|
||||
- name: 'repository'
|
||||
in: 'query'
|
||||
required: true
|
||||
schema:
|
||||
type: 'integer'
|
||||
description: 'ID del ImageRepository'
|
||||
|
||||
ApiPlatform\Metadata\Post:
|
||||
openapiContext:
|
||||
summary: 'Crear un nuevo repositorio Git'
|
||||
description: 'Crea un nuevo repositorio Git en el servidor externo. El ID del ImageRepository debe incluirse en el body del request.'
|
||||
|
||||
ApiPlatform\Metadata\Delete:
|
||||
openapiContext:
|
||||
summary: 'Eliminar un repositorio Git'
|
||||
description: 'Elimina un repositorio Git del servidor externo'
|
||||
parameters:
|
||||
- name: 'repository'
|
||||
in: 'query'
|
||||
required: true
|
||||
schema:
|
||||
type: 'integer'
|
||||
description: 'ID del ImageRepository'
|
||||
|
||||
git_deploy_image:
|
||||
shortName: Git Repository
|
||||
description: Deploy Git image
|
||||
class: ApiPlatform\Metadata\Post
|
||||
method: POST
|
||||
input: App\Dto\Input\DeployGitImageInput
|
||||
uriTemplate: /git-repositories/deploy-image
|
||||
controller: App\Controller\DeployGitImageAction
|
||||
|
||||
properties:
|
||||
App\Entity\GitRepository:
|
||||
id:
|
||||
identifier: false
|
||||
name:
|
||||
identifier: true
|
|
@ -78,19 +78,29 @@ resources:
|
|||
get_collection_images_oggit:
|
||||
shortName: OgRepository Server
|
||||
description: Get collection of image in OgRepository
|
||||
class: ApiPlatform\Metadata\Post
|
||||
method: POST
|
||||
class: ApiPlatform\Metadata\Get
|
||||
method: GET
|
||||
input: false
|
||||
uriTemplate: /image-repositories/server/git/{uuid}/get-collection
|
||||
controller: App\Controller\OgRepository\Git\GetCollectionAction
|
||||
|
||||
git_image_ogrepository_sync:
|
||||
git_repository_commits:
|
||||
shortName: OgRepository Server
|
||||
description: Get commits from a specific branch of a Git repository
|
||||
class: ApiPlatform\Metadata\Post
|
||||
method: POST
|
||||
input: false
|
||||
uriTemplate: /image-repositories/server/git/{uuid}/sync
|
||||
controller: App\Controller\OgRepository\Git\SyncAction
|
||||
input: App\Dto\Input\GetCommitsInput
|
||||
uriTemplate: /image-repositories/server/git/{uuid}/commits
|
||||
controller: App\Controller\OgRepository\Git\GetCommitsAction
|
||||
|
||||
git_repository_branches:
|
||||
shortName: OgRepository Server
|
||||
description: Get branches from a Git repository
|
||||
class: ApiPlatform\Metadata\Post
|
||||
method: POST
|
||||
input: App\Dto\Input\GetBranchesInput
|
||||
uriTemplate: /image-repositories/server/git/{uuid}/branches
|
||||
controller: App\Controller\OgRepository\Git\GetBranchesAction
|
||||
|
||||
properties:
|
||||
App\Entity\ImageRepository:
|
||||
|
|
|
@ -23,6 +23,24 @@ resources:
|
|||
uriTemplate: /traces/server/{uuid}/cancel
|
||||
controller: App\Controller\OgRepository\Image\CancelTransmissionAction
|
||||
|
||||
cancel_multiple_traces:
|
||||
shortName: Trace Server
|
||||
description: Cancel Multiple Traces in OgRepository
|
||||
controller: App\Controller\CancelMultipleTracesAction
|
||||
class: ApiPlatform\Metadata\Post
|
||||
method: POST
|
||||
input: App\Dto\Input\CancelMultipleTracesInput
|
||||
uriTemplate: /traces/cancel-multiple
|
||||
|
||||
kill_job:
|
||||
shortName: Kill Job
|
||||
description: Kill Job in OgAgent
|
||||
controller: App\Controller\OgAgent\KillJobAction
|
||||
class: ApiPlatform\Metadata\Post
|
||||
method: POST
|
||||
input: App\Dto\Input\KillJobInput
|
||||
uriTemplate: /traces/{uuid}/kill-job
|
||||
|
||||
order:
|
||||
createdAt: DESC
|
||||
|
||||
|
|
|
@ -44,19 +44,16 @@ when@prod:
|
|||
level: error
|
||||
formatter: App\Formatter\CustomLineFormatter
|
||||
channels: ["!event"]
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!doctrine"]
|
||||
syslog:
|
||||
type: syslog
|
||||
ident: "ogcore"
|
||||
level: info
|
||||
level: error
|
||||
formatter: App\Formatter\CustomLineFormatter
|
||||
channels: ["!event"]
|
||||
deprecation:
|
||||
type: stream
|
||||
channels: [deprecation]
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
level: error
|
||||
formatter: monolog.formatter.json
|
||||
|
||||
|
|
|
@ -166,8 +166,3 @@ services:
|
|||
bind:
|
||||
$collectionProvider: '@api_platform.doctrine.orm.state.collection_provider'
|
||||
$itemProvider: '@api_platform.doctrine.orm.state.item_provider'
|
||||
|
||||
App\State\Provider\GitImageRepositoryProvider:
|
||||
bind:
|
||||
$collectionProvider: '@api_platform.doctrine.orm.state.collection_provider'
|
||||
$itemProvider: '@api_platform.doctrine.orm.state.item_provider'
|
||||
|
|
|
@ -298,7 +298,7 @@ services:
|
|||
|
||||
api_platform.filter.trace.search:
|
||||
parent: 'api_platform.doctrine.orm.search_filter'
|
||||
arguments: [ { 'id': 'exact', 'command': 'exact', 'client.id': 'exact', status: 'exact' } ]
|
||||
arguments: [ { 'id': 'exact', 'command': 'exact', 'client.id': 'exact', 'status': 'exact' } ]
|
||||
tags: [ 'api_platform.filter' ]
|
||||
|
||||
api_platform.filter.trace.order:
|
||||
|
@ -347,4 +347,28 @@ services:
|
|||
arguments: [ { 'enabled': ~ } ]
|
||||
tags: [ 'api_platform.filter' ]
|
||||
|
||||
api_platform.filter.git_repository.order:
|
||||
parent: 'api_platform.doctrine.orm.order_filter'
|
||||
arguments:
|
||||
$properties: { 'id': ~, 'name': ~ }
|
||||
$orderParameterName: 'order'
|
||||
tags: [ 'api_platform.filter' ]
|
||||
|
||||
api_platform.filter.git_repository.search:
|
||||
parent: 'api_platform.doctrine.orm.search_filter'
|
||||
arguments: [ { 'id': 'exact', 'name': 'partial', 'description': 'partial' } ]
|
||||
tags: [ 'api_platform.filter' ]
|
||||
|
||||
api_platform.filter.git_image_repository.order:
|
||||
parent: 'api_platform.doctrine.orm.order_filter'
|
||||
arguments:
|
||||
$properties: { 'id': ~, 'name': ~, 'status': ~, 'tag': ~, 'branch': ~ }
|
||||
$orderParameterName: 'order'
|
||||
tags: [ 'api_platform.filter' ]
|
||||
|
||||
api_platform.filter.git_image_repository.search:
|
||||
parent: 'api_platform.doctrine.orm.search_filter'
|
||||
arguments: [ { 'id': 'exact', 'name': 'partial', 'status': 'exact', 'tag': 'partial', 'branch': 'partial', 'image.id': 'exact', 'repository.id': 'exact', 'gitRepository.id': 'exact' } ]
|
||||
tags: [ 'api_platform.filter' ]
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20250618114502 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE TABLE git_repository (id INT AUTO_INCREMENT NOT NULL, uuid CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, description VARCHAR(255) DEFAULT NULL, name VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_C2B3204AD17F50A6 (uuid), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
|
||||
$this->addSql('ALTER TABLE git_image_repository ADD git_repository_id INT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE git_image_repository ADD CONSTRAINT FK_E6944D5EDCA00B70 FOREIGN KEY (git_repository_id) REFERENCES git_repository (id)');
|
||||
$this->addSql('CREATE INDEX IDX_E6944D5EDCA00B70 ON git_image_repository (git_repository_id)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE git_image_repository DROP FOREIGN KEY FK_E6944D5EDCA00B70');
|
||||
$this->addSql('DROP TABLE git_repository');
|
||||
$this->addSql('DROP INDEX IDX_E6944D5EDCA00B70 ON git_image_repository');
|
||||
$this->addSql('ALTER TABLE git_image_repository DROP git_repository_id');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20250618115400 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE git_repository ADD repository_id INT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE git_repository ADD CONSTRAINT FK_C2B3204A50C9D4F7 FOREIGN KEY (repository_id) REFERENCES image_repository (id)');
|
||||
$this->addSql('CREATE INDEX IDX_C2B3204A50C9D4F7 ON git_repository (repository_id)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE git_repository DROP FOREIGN KEY FK_C2B3204A50C9D4F7');
|
||||
$this->addSql('DROP INDEX IDX_C2B3204A50C9D4F7 ON git_repository');
|
||||
$this->addSql('ALTER TABLE git_repository DROP repository_id');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20250626145458 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE git_image_repository DROP FOREIGN KEY FK_E6944D5EDCA00B70');
|
||||
$this->addSql('ALTER TABLE git_image_repository DROP FOREIGN KEY FK_E6944D5E3DA5256D');
|
||||
$this->addSql('ALTER TABLE git_image_repository DROP FOREIGN KEY FK_E6944D5E50C9D4F7');
|
||||
$this->addSql('DROP TABLE git_image_repository');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE TABLE git_image_repository (id INT AUTO_INCREMENT NOT NULL, image_id INT NOT NULL, repository_id INT DEFAULT NULL, git_repository_id INT DEFAULT NULL, uuid CHAR(36) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci` COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, updated_by VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, status VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, branch VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, created TINYINT(1) NOT NULL, name VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, tag VARCHAR(255) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, version INT DEFAULT NULL, description VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, UNIQUE INDEX UNIQ_E6944D5ED17F50A6 (uuid), INDEX IDX_E6944D5E3DA5256D (image_id), INDEX IDX_E6944D5E50C9D4F7 (repository_id), INDEX IDX_E6944D5EDCA00B70 (git_repository_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB COMMENT = \'\' ');
|
||||
$this->addSql('ALTER TABLE git_image_repository ADD CONSTRAINT FK_E6944D5EDCA00B70 FOREIGN KEY (git_repository_id) REFERENCES git_repository (id)');
|
||||
$this->addSql('ALTER TABLE git_image_repository ADD CONSTRAINT FK_E6944D5E3DA5256D FOREIGN KEY (image_id) REFERENCES image (id)');
|
||||
$this->addSql('ALTER TABLE git_image_repository ADD CONSTRAINT FK_E6944D5E50C9D4F7 FOREIGN KEY (repository_id) REFERENCES image_repository (id)');
|
||||
}
|
||||
}
|
|
@ -36,7 +36,7 @@ class CheckClientAvailability extends Command
|
|||
$threshold = (new \DateTime())->modify(' - '.self::THRESHOLD_MINUTES . ' minutes');
|
||||
$startQueryTime = microtime(true);
|
||||
|
||||
$validStatuses = [ClientStatus::OG_LIVE, ClientStatus::WINDOWS, ClientStatus::LINUX, ClientStatus::MACOS];
|
||||
$validStatuses = [ClientStatus::OG_LIVE, ClientStatus::WINDOWS, ClientStatus::LINUX, ClientStatus::MACOS, ClientStatus::INITIALIZING, ClientStatus::LINUX_SESSION, ClientStatus::WINDOWS_SESSION];
|
||||
|
||||
$query = $this->entityManager->createQuery(
|
||||
'UPDATE App\Entity\Client c
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use App\Entity\Trace;
|
||||
use App\Model\TraceStatus;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
#[AsCommand(name: 'opengnsys:execute-pending-traces', description: 'Execute pending traces')]
|
||||
class ExecutePendingTracesCommand extends Command
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$startTime = microtime(true);
|
||||
|
||||
$traces = $this->entityManager->getRepository(Trace::class)
|
||||
->findBy(['status' => TraceStatus::PENDING]);
|
||||
|
||||
$count = count($traces);
|
||||
$io->info("Found $count pending traces");
|
||||
|
||||
foreach ($traces as $trace) {
|
||||
$trace->setStatus(TraceStatus::IN_PROGRESS);
|
||||
$this->entityManager->persist($trace);
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
$executionTime = microtime(true) - $startTime;
|
||||
$io->success("Updated $count traces to IN_PROGRESS status");
|
||||
$io->note("Execution time: " . round($executionTime, 3) . "s");
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Dto\Input\CancelMultipleTracesInput;
|
||||
use App\Entity\Trace;
|
||||
use App\Model\TraceStatus;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class CancelMultipleTracesAction extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public function __invoke(CancelMultipleTracesInput $input): JsonResponse
|
||||
{
|
||||
foreach ($input->traces as $trace) {
|
||||
/** @var Trace $trace */
|
||||
$trace = $trace->getEntity();
|
||||
|
||||
$trace->setStatus(TraceStatus::CANCELLED);
|
||||
$this->entityManager->persist($trace);
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
return new JsonResponse(data: 'Traces cancelled successfully', status: Response::HTTP_OK);
|
||||
}
|
||||
}
|
|
@ -42,7 +42,14 @@ class ChangeOrganizationalUnitAction extends AbstractController
|
|||
$clientEntity->setOrganizationalUnit($organizationalUnit);
|
||||
|
||||
$this->entityManager->persist($clientEntity);
|
||||
$this->postAction->__invoke($clientEntity, $clientEntity->getTemplate());
|
||||
|
||||
$template = $clientEntity->getTemplate() ?? $clientEntity->getOrganizationalUnit()->getNetworkSettings()?->getTemplate();
|
||||
|
||||
if (!$template) {
|
||||
throw new BadRequestHttpException('No template found for client');
|
||||
}
|
||||
|
||||
$this->postAction->__invoke($clientEntity, $template);
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use ApiPlatform\Validator\ValidatorInterface;
|
||||
use App\Dto\Input\DeployGitImageInput;
|
||||
use App\Entity\Command;
|
||||
use App\Entity\Image;
|
||||
use App\Model\ClientStatus;
|
||||
use App\Entity\ImageImageRepository;
|
||||
use App\Entity\OrganizationalUnit;
|
||||
use App\Entity\Partition;
|
||||
use App\Model\CommandTypes;
|
||||
use App\Model\DeployMethodTypes;
|
||||
use App\Model\TraceStatus;
|
||||
use App\Service\Trace\CreateService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
class DeployGitImageAction extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
protected readonly EntityManagerInterface $entityManager,
|
||||
protected readonly CreateService $createService,
|
||||
protected readonly ValidatorInterface $validator,
|
||||
public readonly \App\Controller\OgAgent\DeployGitImageAction $deployGitImageOgAgentAction,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
*/
|
||||
public function __invoke(DeployGitImageInput $input): JsonResponse
|
||||
{
|
||||
$this->validator->validate($input);
|
||||
|
||||
$this->handleGitDeployment($input);
|
||||
|
||||
return new JsonResponse(data: [], status: Response::HTTP_OK);
|
||||
}
|
||||
|
||||
private function handleGitDeployment(DeployGitImageInput $input): void
|
||||
{
|
||||
foreach ($input->clients as $client) {
|
||||
$inputData = $this->createInputData($input, $client->getEntity());
|
||||
$this->processDeployment($client->getEntity(), $input, $inputData, DeployMethodTypes::GIT);
|
||||
}
|
||||
}
|
||||
|
||||
private function processDeployment($client, DeployGitImageInput $input, array $inputData, string $deployType): void
|
||||
{
|
||||
$agentJobId = $this->deployGitImageOgAgentAction->__invoke($input, $client);
|
||||
|
||||
if (!$agentJobId) {
|
||||
if ($input->queue) {
|
||||
$this->createService->__invoke($client, CommandTypes::DEPLOY_IMAGE, TraceStatus::PENDING, null, $inputData);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$this->createService->__invoke($client, CommandTypes::DEPLOY_IMAGE, TraceStatus::IN_PROGRESS, $agentJobId, $inputData);
|
||||
}
|
||||
|
||||
private function createInputData(DeployGitImageInput $input, $client): array
|
||||
{
|
||||
return [
|
||||
'method' => $input->method,
|
||||
'client' => $client->getUuid(),
|
||||
'hexsha' => $input->hexsha,
|
||||
'repositoryName' => $input->repositoryName,
|
||||
'branch' => $input->branch,
|
||||
'numDisk' => (string) $input->diskNumber,
|
||||
'numPartition' => (string) $input->partitionNumber,
|
||||
'type' => $input->type,
|
||||
];
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ use ApiPlatform\Validator\ValidatorInterface;
|
|||
use App\Dto\Input\DeployImageInput;
|
||||
use App\Entity\Command;
|
||||
use App\Entity\Image;
|
||||
use App\Model\ClientStatus;
|
||||
use App\Entity\ImageImageRepository;
|
||||
use App\Entity\OrganizationalUnit;
|
||||
use App\Entity\Partition;
|
||||
|
@ -31,11 +32,10 @@ class DeployImageAction extends AbstractController
|
|||
protected readonly EntityManagerInterface $entityManager,
|
||||
protected readonly HttpClientInterface $httpClient,
|
||||
protected readonly CreateService $createService,
|
||||
protected readonly ValidatorInterface $validator,
|
||||
protected readonly ValidatorInterface $validator,
|
||||
public readonly \App\Controller\OgAgent\DeployImageAction $deployImageOgAgentAction,
|
||||
public readonly \App\Controller\OgRepository\Image\DeployImageAction $deployImageOgRepositoryAction,
|
||||
)
|
||||
{
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,90 +47,117 @@ class DeployImageAction extends AbstractController
|
|||
{
|
||||
$this->validator->validate($input);
|
||||
|
||||
switch ($input->method){
|
||||
case DeployMethodTypes::UNICAST:
|
||||
case DeployMethodTypes::UNICAST_DIRECT:
|
||||
foreach ($input->clients as $client) {
|
||||
$inputData = [
|
||||
'method' => $input->method,
|
||||
'client' => $client->getEntity()->getUuid(),
|
||||
'image' => $image->getUuid(),
|
||||
'imageName' => $image->getName(),
|
||||
'numDisk' => (string) $input->diskNumber,
|
||||
'numPartition' => (string) $input->partitionNumber,
|
||||
];
|
||||
|
||||
$agentJobId = $this->deployImageOgAgentAction->__invoke($image, $input, $client->getEntity(), DeployMethodTypes::UNICAST);
|
||||
if (!$agentJobId){
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->createService->__invoke($client->getEntity(), CommandTypes::DEPLOY_IMAGE, TraceStatus::IN_PROGRESS, $agentJobId, $inputData);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case DeployMethodTypes::MULTICAST_UFTP:
|
||||
case DeployMethodTypes::MULTICAST_UFTP_DIRECT:
|
||||
case DeployMethodTypes::MULTICAST_UDPCAST:
|
||||
case DeployMethodTypes::MULTICAST_UDPCAST_DIRECT:
|
||||
foreach ($input->clients as $client) {
|
||||
$inputData = [
|
||||
'method' => $input->method,
|
||||
'client' => $client->getEntity()->getUuid(),
|
||||
'image' => $image->getUuid(),
|
||||
'mcastIp' => $input->mcastIp,
|
||||
'mcastPort' => $input->mcastPort,
|
||||
'mcastSpeed' => $input->mcastSpeed,
|
||||
'mcastMode' => $input->mcastMode,
|
||||
'numDisk' => (string) $input->diskNumber,
|
||||
'numPartition' => (string) $input->partitionNumber,
|
||||
];
|
||||
|
||||
try {
|
||||
$this->deployImageOgRepositoryAction->__invoke($input, $image, $client->getEntity());
|
||||
} catch (\Exception $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$agentJobId = $this->deployImageOgAgentAction->__invoke($image, $input, $client->getEntity(), DeployMethodTypes::MULTICAST);
|
||||
if (!$agentJobId){
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->createService->__invoke($client->getEntity(), CommandTypes::DEPLOY_IMAGE, TraceStatus::IN_PROGRESS, $agentJobId, $inputData);
|
||||
}
|
||||
break;
|
||||
|
||||
case DeployMethodTypes::TORRENT:
|
||||
foreach ($input->clients as $client) {
|
||||
$inputData = [
|
||||
'method' => $input->method,
|
||||
'client' => $client->getEntity()->getUuid(),
|
||||
'image' => $image->getUuid(),
|
||||
'p2pMode' => $input->p2pMode,
|
||||
'p2pTime' => $input->p2pTime,
|
||||
'numDisk' => (string) $input->diskNumber,
|
||||
'numPartition' => (string) $input->partitionNumber,
|
||||
];
|
||||
|
||||
try {
|
||||
$this->deployImageOgRepositoryAction->__invoke($input, $image, $client->getEntity(), $this->httpClient);
|
||||
} catch (\Exception $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$agentJobId = $this->deployImageOgAgentAction->__invoke($image, $input, $client->getEntity(), DeployMethodTypes::TORRENT);
|
||||
if (!$agentJobId){
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->createService->__invoke($client->getEntity(), CommandTypes::DEPLOY_IMAGE, TraceStatus::IN_PROGRESS, $agentJobId, $inputData);
|
||||
}
|
||||
|
||||
break;
|
||||
if ($input->type === 'monolithic') {
|
||||
$this->handleMonolithicDeployment($input, $image);
|
||||
}
|
||||
|
||||
return new JsonResponse(data: [], status: Response::HTTP_OK);
|
||||
}
|
||||
|
||||
private function handleMonolithicDeployment(DeployImageInput $input, ImageImageRepository $image): void
|
||||
{
|
||||
switch ($input->method) {
|
||||
case DeployMethodTypes::UNICAST:
|
||||
case DeployMethodTypes::UNICAST_DIRECT:
|
||||
$this->handleUnicastDeployment($input, $image);
|
||||
break;
|
||||
case DeployMethodTypes::MULTICAST_UFTP:
|
||||
case DeployMethodTypes::MULTICAST_UFTP_DIRECT:
|
||||
case DeployMethodTypes::MULTICAST_UDPCAST:
|
||||
case DeployMethodTypes::MULTICAST_UDPCAST_DIRECT:
|
||||
$this->handleMulticastDeployment($input, $image);
|
||||
break;
|
||||
case DeployMethodTypes::TORRENT:
|
||||
$this->handleTorrentDeployment($input, $image);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function handleUnicastDeployment(DeployImageInput $input, ImageImageRepository $image): void
|
||||
{
|
||||
foreach ($input->clients as $client) {
|
||||
$inputData = $this->createInputData($input, $image, $client->getEntity());
|
||||
$this->processDeployment($client->getEntity(), $input, $image, $inputData, DeployMethodTypes::UNICAST);
|
||||
}
|
||||
}
|
||||
|
||||
private function handleMulticastDeployment(DeployImageInput $input, ImageImageRepository $image): void
|
||||
{
|
||||
foreach ($input->clients as $client) {
|
||||
$inputData = $this->createMulticastInputData($input, $image, $client->getEntity());
|
||||
|
||||
try {
|
||||
$this->deployImageOgRepositoryAction->__invoke($input, $image, $client->getEntity());
|
||||
} catch (\Exception $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->processDeployment($client->getEntity(), $input, $image, $inputData, DeployMethodTypes::MULTICAST);
|
||||
}
|
||||
}
|
||||
|
||||
private function handleTorrentDeployment(DeployImageInput $input, ImageImageRepository $image): void
|
||||
{
|
||||
foreach ($input->clients as $client) {
|
||||
$inputData = $this->createTorrentInputData($input, $image, $client->getEntity());
|
||||
|
||||
try {
|
||||
$response = $this->deployImageOgRepositoryAction->__invoke($input, $image, $client->getEntity(), $this->httpClient);
|
||||
|
||||
if (is_array($response) && isset($response['code']) && $response['code'] === 500) {
|
||||
throw new \Exception('Error del servidor OgRepository: ' . ($response['error'] ?? 'Error desconocido') . ' - ' . ($response['details'] ?? ''));
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$this->processDeployment($client->getEntity(), $input, $image, $inputData, DeployMethodTypes::TORRENT);
|
||||
}
|
||||
}
|
||||
|
||||
private function processDeployment($client, DeployImageInput $input, ImageImageRepository $image, array $inputData, string $deployType): void
|
||||
{
|
||||
$agentJobId = $this->deployImageOgAgentAction->__invoke($image, $input, $client, $deployType);
|
||||
|
||||
if (!$agentJobId) {
|
||||
if ($input->queue) {
|
||||
$this->createService->__invoke($client, CommandTypes::DEPLOY_IMAGE, TraceStatus::PENDING, null, $inputData);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$this->createService->__invoke($client, CommandTypes::DEPLOY_IMAGE, TraceStatus::IN_PROGRESS, $agentJobId, $inputData);
|
||||
}
|
||||
|
||||
private function createInputData(DeployImageInput $input, ImageImageRepository $image, $client): array
|
||||
{
|
||||
return [
|
||||
'method' => $input->method,
|
||||
'client' => $client->getUuid(),
|
||||
'image' => $image->getUuid(),
|
||||
'imageName' => $image->getName(),
|
||||
'numDisk' => (string) $input->diskNumber,
|
||||
'numPartition' => (string) $input->partitionNumber,
|
||||
'type' => $input->type,
|
||||
];
|
||||
}
|
||||
|
||||
private function createMulticastInputData(DeployImageInput $input, ImageImageRepository $image, $client): array
|
||||
{
|
||||
return array_merge($this->createInputData($input, $image, $client), [
|
||||
'mcastIp' => $input->mcastIp,
|
||||
'mcastPort' => $input->mcastPort,
|
||||
'mcastSpeed' => $input->mcastSpeed,
|
||||
'mcastMode' => $input->mcastMode,
|
||||
]);
|
||||
}
|
||||
|
||||
private function createTorrentInputData(DeployImageInput $input, ImageImageRepository $image, $client): array
|
||||
{
|
||||
return array_merge($this->createInputData($input, $image, $client), [
|
||||
'p2pMode' => $input->p2pMode,
|
||||
'p2pTime' => $input->p2pTime,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace App\Controller\OgAgent;
|
||||
|
||||
use App\Controller\OgRepository\Git\CreateRepositoryAction;
|
||||
use App\Controller\OgRepository\Git\CreateTagAction;
|
||||
use App\Controller\OgRepository\Git\SshKeyAction;
|
||||
use App\Service\CreatePartitionService;
|
||||
use App\Service\Trace\CreateService;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
@ -28,7 +28,7 @@ abstract class AbstractOgAgentController extends AbstractController
|
|||
protected readonly LoggerInterface $logger,
|
||||
protected readonly CreateService $createService,
|
||||
protected readonly CreateRepositoryAction $createRepositoryAction,
|
||||
protected readonly CreateTagAction $createTagAction,
|
||||
protected readonly SshKeyAction $sshKeyAction,
|
||||
#[Autowire(env: 'SSL_ENABLED')]
|
||||
private readonly string $sslEnabled,
|
||||
)
|
||||
|
|
|
@ -5,10 +5,9 @@ declare(strict_types=1);
|
|||
namespace App\Controller\OgAgent;
|
||||
|
||||
use App\Controller\OgRepository\Git\CreateRepositoryAction;
|
||||
use App\Controller\OgRepository\Git\CreateTagAction;
|
||||
use App\Entity\Client;
|
||||
use App\Entity\Command;
|
||||
use App\Entity\GitImageRepository;
|
||||
use App\Entity\GitRepository;
|
||||
use App\Entity\Image;
|
||||
use App\Entity\ImageImageRepository;
|
||||
use App\Entity\ImageRepository;
|
||||
|
@ -43,9 +42,11 @@ class CreateImageAction extends AbstractOgAgentController
|
|||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function __invoke(Image $image, ?Partition $partition = null, ?Client $client = null): JsonResponse
|
||||
public function __invoke(bool $queue, Image $image, ?Partition $partition = null, ?Client $client = null, ?string $gitRepositoryName = null): JsonResponse
|
||||
{
|
||||
if (!$image->getClient()->getIp()) {
|
||||
$client = $client ?? $image->getClient();
|
||||
|
||||
if (!$client->getIp()) {
|
||||
throw new BadRequestHttpException('IP is required');
|
||||
}
|
||||
|
||||
|
@ -76,25 +77,13 @@ class CreateImageAction extends AbstractOgAgentController
|
|||
|
||||
$this->entityManager->persist($imageImageRepository);
|
||||
|
||||
return $this->createMonolithicImage($imageImageRepository, $partitionInfo, $image, $repository, $client);
|
||||
return $this->createMonolithicImage($imageImageRepository, $partitionInfo, $image, $repository, $client, $queue);
|
||||
} else {
|
||||
$repository = $image->getClient()->getRepository();
|
||||
$latestImageRepo = $this->entityManager->getRepository(GitImageRepository::class)->findLatestVersionByImageAndRepository($image, $repository);
|
||||
|
||||
$gitImageRepository = new GitImageRepository();
|
||||
$gitImageRepository->setName($image->getName().'_v'.($latestImageRepo ? $latestImageRepo->getVersion() + 1 : 1));
|
||||
$gitImageRepository->setImage($image);
|
||||
$gitImageRepository->setRepository($repository);
|
||||
$gitImageRepository->setStatus(ImageStatus::IN_PROGRESS);
|
||||
$gitImageRepository->setVersion($latestImageRepo ? $latestImageRepo->getVersion() + 1 : 1);
|
||||
$gitImageRepository->setTag('v'.($latestImageRepo ? $latestImageRepo->getVersion() + 1 : 1));
|
||||
$gitImageRepository->setCreated(false);
|
||||
|
||||
$this->entityManager->persist($gitImageRepository);
|
||||
$this->entityManager->persist($image);
|
||||
$this->entityManager->flush();
|
||||
|
||||
return $this->createGitImage($gitImageRepository, $partitionInfo, $image, $repository);
|
||||
|
||||
// Para imágenes Git, no necesitamos crear entidades en la base de datos
|
||||
// ya que los repositorios Git son datos externos
|
||||
return $this->createGitImage($image, $partitionInfo, $repository, $queue, $gitRepositoryName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,9 +98,19 @@ class CreateImageAction extends AbstractOgAgentController
|
|||
array $partitionInfo,
|
||||
Image $image,
|
||||
ImageRepository $repository,
|
||||
?Client $client = null
|
||||
?Client $client = null,
|
||||
bool $queue = false
|
||||
): JsonResponse
|
||||
{
|
||||
if (!isset($partitionInfo['numDisk'], $partitionInfo['numPartition'], $partitionInfo['partitionCode'], $partitionInfo['filesystem'])) {
|
||||
throw new BadRequestHttpException('Missing required partition information');
|
||||
}
|
||||
|
||||
$client = $client ?? $image->getClient();
|
||||
if (!$client->getIp() || !$client->getToken()) {
|
||||
throw new BadRequestHttpException('Client IP or token is missing');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'dsk' => (string) $partitionInfo['numDisk'],
|
||||
'par' => (string) $partitionInfo['numPartition'],
|
||||
|
@ -134,85 +133,219 @@ class CreateImageAction extends AbstractOgAgentController
|
|||
|
||||
$data['cpt'] = dechex($partitionTypeCode);
|
||||
} else {
|
||||
throw new Exception("El tipo de partición '$partitionCode' no se encontró en la lista.");
|
||||
throw new BadRequestHttpException("Invalid partition code: {$partitionCode}");
|
||||
}
|
||||
|
||||
$client = $client ?? $image->getClient();
|
||||
$this->logger->info('Creating image', ['image' => $image->getId()]);
|
||||
|
||||
$response = $this->createRequest(
|
||||
method: 'POST',
|
||||
url: 'https://'.$client->getIp().':8000/opengnsys/CrearImagen',
|
||||
params: [
|
||||
'json' => $data,
|
||||
],
|
||||
token: $client->getToken(),
|
||||
);
|
||||
try {
|
||||
$response = $this->createRequest(
|
||||
method: 'POST',
|
||||
url: 'https://'.$client->getIp().':8000/opengnsys/CrearImagen',
|
||||
params: [
|
||||
'json' => $data,
|
||||
],
|
||||
token: $client->getToken(),
|
||||
);
|
||||
|
||||
$this->logger->info('Creating image', ['image' => $imageImageRepository->getName(), 'repository' => $repository->getIp()]);
|
||||
$this->logger->info('Creating image', ['image' => $imageImageRepository->getName(), 'repository' => $repository->getIp()]);
|
||||
|
||||
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
|
||||
throw new BadRequestHttpException('Error creating image');
|
||||
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
|
||||
if ($queue) {
|
||||
$inputData = [
|
||||
'method' => 'CrearImagen',
|
||||
'type' => 'monolithic',
|
||||
'client' => $client->getUuid(),
|
||||
'image' => $image->getUuid(),
|
||||
'partitionCode' => $partitionInfo['partitionCode'],
|
||||
'partitionType' => $partitionInfo['filesystem'],
|
||||
'repository' => $repository->getIp(),
|
||||
'name' => $image->getName().'_v'.$imageImageRepository->getVersion(),
|
||||
];
|
||||
$this->createService->__invoke($client, CommandTypes::CREATE_IMAGE, TraceStatus::PENDING, null, $inputData);
|
||||
return new JsonResponse(data: [], status: Response::HTTP_OK);
|
||||
}
|
||||
|
||||
throw new BadRequestHttpException('Error creating image: ' . ($response['message'] ?? 'Unknown error'));
|
||||
}
|
||||
|
||||
if (!isset($response['job_id'])) {
|
||||
throw new BadRequestHttpException('No job ID received from server');
|
||||
}
|
||||
|
||||
$jobId = $response['job_id'];
|
||||
|
||||
try {
|
||||
$client->setStatus(ClientStatus::BUSY);
|
||||
$imageImageRepository->setStatus(ImageStatus::IN_PROGRESS);
|
||||
|
||||
$this->entityManager->persist($client);
|
||||
$this->entityManager->persist($imageImageRepository);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$inputData = [
|
||||
'method' => 'CrearImagen',
|
||||
'type' => 'monolithic',
|
||||
'client' => $client->getUuid(),
|
||||
'image' => $image->getUuid(),
|
||||
'partitionCode' => $partitionInfo['partitionCode'],
|
||||
'partitionType' => $partitionInfo['filesystem'],
|
||||
'repository' => $repository->getIp(),
|
||||
'name' => $image->getName().'_v'.$imageImageRepository->getVersion(),
|
||||
];
|
||||
|
||||
$this->createService->__invoke(
|
||||
$image->getClient(),
|
||||
CommandTypes::CREATE_IMAGE,
|
||||
TraceStatus::IN_PROGRESS,
|
||||
$jobId,
|
||||
$inputData
|
||||
);
|
||||
|
||||
return new JsonResponse(data: $image, status: Response::HTTP_OK);
|
||||
} catch (Exception $e) {
|
||||
$client->setStatus(ClientStatus::OG_LIVE);
|
||||
$this->entityManager->persist($client);
|
||||
$this->entityManager->flush();
|
||||
throw $e;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$this->logger->error('Error in monolithic image creation process', [
|
||||
'repository' => $repository->getId(),
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return new JsonResponse(
|
||||
data: ['error' => $e->getMessage()],
|
||||
status: Response::HTTP_INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
$jobId = $response['job_id'];
|
||||
|
||||
$client->setStatus(ClientStatus::BUSY);
|
||||
$this->entityManager->persist($client);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$inputData = [
|
||||
'method' => 'CrearImagen',
|
||||
'type' => 'monolithic',
|
||||
'client' => $client->getUuid(),
|
||||
'image' => $image->getUuid(),
|
||||
'partitionCode' => $partitionInfo['partitionCode'],
|
||||
'partitionType' => $partitionInfo['filesystem'],
|
||||
'repository' => $repository->getIp(),
|
||||
'name' => $image->getName().'_v'.$imageImageRepository->getVersion(),
|
||||
];
|
||||
|
||||
$this->createService->__invoke($image->getClient(), CommandTypes::CREATE_IMAGE, TraceStatus::IN_PROGRESS, $jobId, $inputData);
|
||||
|
||||
return new JsonResponse(data: $image, status: Response::HTTP_OK);
|
||||
}
|
||||
|
||||
public function createGitImage(
|
||||
GitImageRepository $gitImageRepository,
|
||||
array $partitionInfo,
|
||||
Image $image,
|
||||
ImageRepository $repository
|
||||
array $partitionInfo,
|
||||
ImageRepository $repository,
|
||||
bool $queue = false,
|
||||
?string $gitRepositoryName = null
|
||||
): JsonResponse
|
||||
{
|
||||
if (!isset($partitonInfo)) {
|
||||
try {
|
||||
$this->createRepositoryAction->__invoke($image, $repository);
|
||||
} catch (Exception $e) {
|
||||
$this->logger->error('Error creating repository', ['repository' => $repository->getId(), 'error' => $e->getMessage()]);
|
||||
|
||||
return new JsonResponse(
|
||||
data: ['error' => $e->getMessage()],
|
||||
status: Response::HTTP_INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
$this->createTagAction->__invoke($image, $repository, $gitImageRepository);
|
||||
} catch (Exception $e) {
|
||||
$this->logger->error('Error creating tag', ['repository' => $repository->getId(), 'error' => $e->getMessage()]);
|
||||
|
||||
return new JsonResponse(
|
||||
data: ['error' => $e->getMessage()],
|
||||
status: Response::HTTP_INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
if (!isset($partitionInfo['numDisk'], $partitionInfo['numPartition'], $partitionInfo['partitionCode'], $partitionInfo['filesystem'])) {
|
||||
throw new BadRequestHttpException('Missing required partition information');
|
||||
}
|
||||
|
||||
return new JsonResponse(
|
||||
data: ['message' => 'Repository created successfully'],
|
||||
status: Response::HTTP_OK
|
||||
);
|
||||
$client = $image->getClient();
|
||||
if (!$client->getIp() || !$client->getToken()) {
|
||||
throw new BadRequestHttpException('Client IP or token is missing');
|
||||
}
|
||||
|
||||
//TODO: llamar al endpoint del agente.
|
||||
try {
|
||||
$data = [
|
||||
'dsk' => (string) $partitionInfo['numDisk'],
|
||||
'par' => (string) $partitionInfo['numPartition'],
|
||||
'cpt' => null,
|
||||
'idi' => $gitRepositoryName ?: $image->getUuid(),
|
||||
'nci' => $gitRepositoryName ?: $image->getName(),
|
||||
'ipr' => $repository->getIp(),
|
||||
'nfn' => 'CrearImagenGit',
|
||||
'tag' => '',
|
||||
'ids' => '0'
|
||||
];
|
||||
|
||||
$partitionTypes = PartitionTypes::getPartitionTypes();
|
||||
$partitionCode = $partitionInfo['partitionCode'];
|
||||
$cptKey = array_search($partitionCode, array_column($partitionTypes, 'name'), true);
|
||||
|
||||
if ($cptKey !== false) {
|
||||
$keys = array_keys($partitionTypes);
|
||||
$partitionTypeCode = $keys[$cptKey];
|
||||
$data['cpt'] = dechex($partitionTypeCode);
|
||||
} else {
|
||||
throw new BadRequestHttpException("Invalid partition code: {$partitionCode}");
|
||||
}
|
||||
|
||||
//$this->sshKeyAction->__invoke($repository, $client);
|
||||
|
||||
$response = $this->createRequest(
|
||||
method: 'POST',
|
||||
url: 'https://'.$client->getIp().':8000/opengnsys/CrearImagenGit',
|
||||
params: [
|
||||
'json' => $data,
|
||||
],
|
||||
token: $client->getToken(),
|
||||
);
|
||||
|
||||
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
|
||||
if ($queue) {
|
||||
$inputData = [
|
||||
'method' => 'CrearImagenGit',
|
||||
'type' => 'git',
|
||||
'client' => $client->getUuid(),
|
||||
'image' => $image->getUuid(),
|
||||
'partitionCode' => $partitionInfo['partitionCode'],
|
||||
'partitionType' => $partitionInfo['filesystem'],
|
||||
'repository' => $repository->getIp(),
|
||||
'name' => $image->getName(),
|
||||
];
|
||||
|
||||
$this->createService->__invoke($client, CommandTypes::CREATE_IMAGE_GIT, TraceStatus::PENDING, null, $inputData);
|
||||
return new JsonResponse(data: [], status: Response::HTTP_OK);
|
||||
}
|
||||
|
||||
throw new BadRequestHttpException('Error creating image: ' . ($response['message'] ?? 'Unknown error'));
|
||||
}
|
||||
|
||||
if (!isset($response['job_id'])) {
|
||||
throw new BadRequestHttpException('No job ID received from server');
|
||||
}
|
||||
|
||||
$jobId = $response['job_id'];
|
||||
|
||||
try {
|
||||
$client->setStatus(ClientStatus::BUSY);
|
||||
|
||||
$this->entityManager->persist($client);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$inputData = [
|
||||
'method' => 'CrearImagenGit',
|
||||
'type' => 'git',
|
||||
'client' => $client->getUuid(),
|
||||
'image' => $image->getUuid(),
|
||||
'partitionCode' => $partitionInfo['partitionCode'],
|
||||
'partitionType' => $partitionInfo['filesystem'],
|
||||
'repository' => $repository->getIp(),
|
||||
'name' => $image->getName(),
|
||||
];
|
||||
|
||||
$this->createService->__invoke(
|
||||
$image->getClient(),
|
||||
CommandTypes::CREATE_IMAGE_GIT,
|
||||
TraceStatus::IN_PROGRESS,
|
||||
$jobId,
|
||||
$inputData
|
||||
);
|
||||
|
||||
return new JsonResponse(data: $image, status: Response::HTTP_OK);
|
||||
} catch (Exception $e) {
|
||||
$client->setStatus(ClientStatus::OG_LIVE);
|
||||
$this->entityManager->persist($client);
|
||||
$this->entityManager->flush();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$this->logger->error('Error in git image creation process', [
|
||||
'repository' => $repository->getId(),
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return new JsonResponse(
|
||||
data: ['error' => $e->getMessage()],
|
||||
status: Response::HTTP_INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\OgAgent;
|
||||
|
||||
use App\Dto\Input\DeployGitImageInput;
|
||||
use App\Entity\Client;
|
||||
use App\Entity\Image;
|
||||
use App\Model\ClientStatus;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
|
||||
class DeployGitImageAction extends AbstractOgAgentController
|
||||
{
|
||||
/**
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
*/
|
||||
public function __invoke(DeployGitImageInput $input, Client $client)
|
||||
{
|
||||
if (!$client->getIp()) {
|
||||
throw new BadRequestHttpException('IP is required');
|
||||
}
|
||||
|
||||
if (!$input->hexsha && !$input->tag) {
|
||||
throw new BadRequestHttpException('Either hexsha or tag is required for Git image deployment');
|
||||
}
|
||||
|
||||
if (!$input->repositoryName) {
|
||||
throw new BadRequestHttpException('Repository name is required for Git image deployment');
|
||||
}
|
||||
|
||||
if (!$input->branch) {
|
||||
throw new BadRequestHttpException('Branch is required for Git image deployment');
|
||||
}
|
||||
|
||||
$repository = $client->getRepository();
|
||||
|
||||
$data = [
|
||||
'dsk' => (string) $input->diskNumber,
|
||||
'par' => (string) $input->partitionNumber,
|
||||
'ifs' => "1",
|
||||
'idi' => 1,
|
||||
'nci' => $input->repositoryName,
|
||||
'ipr' => $repository->getIp(),
|
||||
'nfn' => 'RestaurarImagenGit',
|
||||
'ptc' => 'git',
|
||||
'ids' => '0',
|
||||
'ref' => $input->hexsha ?? $input->tag
|
||||
];
|
||||
|
||||
$url = 'https://'.$client->getIp().':8000/opengnsys/RestaurarImagenGit';
|
||||
|
||||
$response = $this->createRequest(
|
||||
method: 'POST',
|
||||
url: $url,
|
||||
params: [
|
||||
'json' => $data,
|
||||
],
|
||||
token: $client->getToken(),
|
||||
);
|
||||
|
||||
$this->logger->info('Deploying Git image', [
|
||||
'repository' => $input->repositoryName,
|
||||
'branch' => $input->branch,
|
||||
'ref' => $input->hexsha ?? $input->tag,
|
||||
'client' => $client->getIp()
|
||||
]);
|
||||
|
||||
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
|
||||
throw new BadRequestHttpException('Error deploying Git image');
|
||||
}
|
||||
|
||||
$jobId = $response['job_id'];
|
||||
|
||||
$client->setStatus(ClientStatus::BUSY);
|
||||
$this->entityManager->persist($client);
|
||||
$this->entityManager->flush();
|
||||
|
||||
return $jobId;
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@ class DeployImageAction extends AbstractOgAgentController
|
|||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
*/
|
||||
public function __invoke(ImageImageRepository $imageImageRepository, DeployImageInput $input, Client $client, string $method)
|
||||
public function __invoke(ImageImageRepository $imageImageRepository, DeployImageInput $input, Client $client, ?string $method = null)
|
||||
{
|
||||
$image = $imageImageRepository->getImage();
|
||||
|
||||
|
@ -46,6 +46,10 @@ class DeployImageAction extends AbstractOgAgentController
|
|||
throw new BadRequestHttpException('IP is required');
|
||||
}
|
||||
|
||||
if ($input->type === 'git') {
|
||||
throw new BadRequestHttpException('Use DeployGitImageAction for Git images');
|
||||
}
|
||||
|
||||
$method = match ($input->method) {
|
||||
DeployMethodTypes::MULTICAST_UFTP_DIRECT, DeployMethodTypes::MULTICAST_UDPCAST_DIRECT, => 'multicast-direct',
|
||||
DeployMethodTypes::MULTICAST, DeployMethodTypes::MULTICAST_UFTP, DeployMethodTypes::MULTICAST_UDPCAST => 'multicast',
|
||||
|
@ -83,16 +87,22 @@ class DeployImageAction extends AbstractOgAgentController
|
|||
'ids' => '0'
|
||||
];
|
||||
|
||||
$url = 'https://'.$client->getIp().':8000/opengnsys/RestaurarImagen';
|
||||
|
||||
$response = $this->createRequest(
|
||||
method: 'POST',
|
||||
url: 'https://'.$client->getIp().':8000/opengnsys/RestaurarImagen',
|
||||
url: $url,
|
||||
params: [
|
||||
'json' => $data,
|
||||
],
|
||||
token: $client->getToken(),
|
||||
);
|
||||
|
||||
$this->logger->info('Deploying image', [ 'image' => $imageImageRepository->getName(), 'repository' => $repository->getIp()]);
|
||||
$this->logger->info('Deploying image', [
|
||||
'image' => $imageImageRepository->getName(),
|
||||
'repository' => $repository->getIp(),
|
||||
'client' => $client->getIp()
|
||||
]);
|
||||
|
||||
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
|
||||
throw new BadRequestHttpException('Error deploying image');
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\OgAgent;
|
||||
|
||||
use App\Dto\Input\KillJobInput;
|
||||
use App\Entity\Trace;
|
||||
use App\Model\ClientStatus;
|
||||
use App\Model\CommandTypes;
|
||||
use App\Model\TraceStatus;
|
||||
use App\Service\Trace\CreateService;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
|
||||
class KillJobAction extends AbstractOgAgentController
|
||||
{
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function __invoke(Trace $trace, KillJobInput $input): JsonResponse
|
||||
{
|
||||
$client = $trace->getClient();
|
||||
|
||||
if (!$client->getIp()) {
|
||||
throw new BadRequestHttpException('IP is required');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'job_id' => $input->jobId
|
||||
];
|
||||
|
||||
$response = $this->createRequest(
|
||||
method: 'POST',
|
||||
url: 'https://'.$client->getIp().':8000/opengnsys/KillJob',
|
||||
params: [
|
||||
'json' => $data,
|
||||
],
|
||||
token: $client->getToken(),
|
||||
);
|
||||
|
||||
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
|
||||
throw new BadRequestHttpException('Error killing job: '.$response['error']);
|
||||
}
|
||||
|
||||
$this->logger->info('Killing job', ['client' => $client->getId(), 'job_id' => $input->jobId]);
|
||||
|
||||
$trace->setStatus(TraceStatus::CANCELLED);
|
||||
$this->entityManager->persist($trace);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$inputData = [
|
||||
'job_id' => $input->jobId,
|
||||
'client' => $client->getId(),
|
||||
'trace' => $trace->getUuid(),
|
||||
'command' => $trace->getCommand(),
|
||||
];
|
||||
|
||||
$this->createService->__invoke($client, CommandTypes::KILL_JOB, TraceStatus::CANCELLED, $input->jobId, $inputData);
|
||||
|
||||
return new JsonResponse(data: $trace, status: Response::HTTP_OK);
|
||||
}
|
||||
}
|
|
@ -53,7 +53,8 @@ class LoginAction extends AbstractOgAgentController
|
|||
}
|
||||
|
||||
if ($client->getStatus() !== ClientStatus::OG_LIVE) {
|
||||
throw new BadRequestHttpException('Client is not in OG_LIVE status');
|
||||
$this->createService->__invoke($client, CommandTypes::LOGIN, TraceStatus::PENDING, null, []);
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = [
|
||||
|
@ -73,7 +74,8 @@ class LoginAction extends AbstractOgAgentController
|
|||
);
|
||||
|
||||
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
|
||||
throw new BadRequestHttpException('Error logging in: '.$response['error']);
|
||||
$this->createService->__invoke($client, CommandTypes::LOGIN, TraceStatus::PENDING, null, []);
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->logger->info('Login client', ['client' => $client->getId()]);
|
||||
|
|
|
@ -111,7 +111,12 @@ class PartitionAssistantAction extends AbstractOgAgentController
|
|||
$this->logger->info('Partition assistant', ['client' => $client->getId()]);
|
||||
|
||||
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
|
||||
throw new BadRequestHttpException('Error occurred while partitioning');
|
||||
if ($input->queue) {
|
||||
$this->createService->__invoke($client, CommandTypes::PARTITION_AND_FORMAT, TraceStatus::PENDING, null, $data);
|
||||
continue;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$jobId = $response['job_id'];
|
||||
|
|
|
@ -47,12 +47,10 @@ class PowerOffAction extends AbstractOgAgentController
|
|||
throw new BadRequestHttpException('IP is required');
|
||||
}
|
||||
|
||||
if ($client->getStatus() === ClientStatus::OFF) {
|
||||
if ($client->getStatus() === ClientStatus::OFF || $client->getStatus() === ClientStatus::TURNING_OFF || $client->getStatus() === ClientStatus::DISCONNECTED) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$endpoint = $client->getStatus() === ClientStatus::OG_LIVE ? 'opengnsys/Apagar' : 'opengnsys/poweroff';
|
||||
|
||||
$data = [
|
||||
'nfn' => 'Apagar',
|
||||
'ids' => '0'
|
||||
|
@ -60,7 +58,7 @@ class PowerOffAction extends AbstractOgAgentController
|
|||
|
||||
$response = $this->createRequest(
|
||||
method: 'POST',
|
||||
url: 'https://'.$client->getIp().':8000/'.$endpoint,
|
||||
url: 'https://'.$client->getIp().':8000/opengnsys/Apagar',
|
||||
params: [
|
||||
'json' => $data,
|
||||
],
|
||||
|
@ -68,7 +66,14 @@ class PowerOffAction extends AbstractOgAgentController
|
|||
);
|
||||
|
||||
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
|
||||
throw new BadRequestHttpException('Error deploying image');
|
||||
$this->logger->error('Error powering off client', ['client' => $client->getId(), 'error' => $response['error']]);
|
||||
|
||||
if ($input->queue) {
|
||||
$this->createService->__invoke($client, CommandTypes::SHUTDOWN, TraceStatus::PENDING, null, []);
|
||||
continue;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->logger->info('Powering off client', ['client' => $client->getId()]);
|
||||
|
|
|
@ -47,8 +47,6 @@ class RebootAction extends AbstractOgAgentController
|
|||
throw new BadRequestHttpException('IP is required');
|
||||
}
|
||||
|
||||
$endpoint = $client->getStatus() === ClientStatus::OG_LIVE ? 'opengnsys/Reiniciar' : '/opengnsys/reboot';
|
||||
|
||||
$data = [
|
||||
'nfn' => 'Reiniciar',
|
||||
'ids' => '0'
|
||||
|
@ -56,7 +54,7 @@ class RebootAction extends AbstractOgAgentController
|
|||
|
||||
$response = $this->createRequest(
|
||||
method: 'POST',
|
||||
url: 'https://'.$client->getIp().':8000/'.$endpoint,
|
||||
url: 'https://'.$client->getIp().':8000/opengnsys/Reiniciar',
|
||||
params: [
|
||||
'json' => $data,
|
||||
],
|
||||
|
@ -64,7 +62,12 @@ class RebootAction extends AbstractOgAgentController
|
|||
);
|
||||
|
||||
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
|
||||
throw new BadRequestHttpException('Error deploying image');
|
||||
if ($input->queue) {
|
||||
$this->createService->__invoke($client, CommandTypes::REBOOT, TraceStatus::PENDING, null, []);
|
||||
continue;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->logger->info('Rebooting client', ['client' => $client->getId()]);
|
||||
|
|
|
@ -43,10 +43,11 @@ class RemoveCacheImageAction extends AbstractOgAgentController
|
|||
}
|
||||
|
||||
if ($client->getStatus() !== ClientStatus::OG_LIVE) {
|
||||
throw new BadRequestHttpException('Client is not in OG_LIVE status');
|
||||
$this->createService->__invoke($client, CommandTypes::REMOVE_CACHE_IMAGE, TraceStatus::PENDING, null, []);
|
||||
continue;
|
||||
}
|
||||
|
||||
$script = `rm%20-r%20/opt/opengnsys/cache/opt/opengnsys/images/{$partition->getImage()->getName()}.*@'`;
|
||||
$script = 'rm -r /opt/opengnsys/cache/opt/opengnsys/images/' . $partition->getImage()->getName() . '.*';
|
||||
|
||||
$data = [
|
||||
'nfn' => 'EjecutarScript',
|
||||
|
@ -64,9 +65,13 @@ class RemoveCacheImageAction extends AbstractOgAgentController
|
|||
);
|
||||
|
||||
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
|
||||
throw new BadRequestHttpException('Error logging in: '.$response['error']);
|
||||
if ($input->queue) {
|
||||
$this->createService->__invoke($client, CommandTypes::REMOVE_CACHE_IMAGE, TraceStatus::PENDING, null, []);
|
||||
continue;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->logger->info('Login client', ['client' => $client->getId()]);
|
||||
|
||||
$jobId = $response['job_id'];
|
||||
|
|
|
@ -57,7 +57,17 @@ class RunScriptAction extends AbstractOgAgentController
|
|||
);
|
||||
|
||||
if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
|
||||
throw new BadRequestHttpException('Error deploying image');
|
||||
$this->logger->error('Error running script', ['client' => $client->getId(), 'error' => $response['error']]);
|
||||
|
||||
if ($input->queue) {
|
||||
$inputData = [
|
||||
'script' => $input->script,
|
||||
];
|
||||
$this->createService->__invoke($client, CommandTypes::RUN_SCRIPT, TraceStatus::PENDING, null, $inputData);
|
||||
continue;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->logger->info('Powering off client', ['client' => $client->getId()]);
|
||||
|
|
|
@ -166,14 +166,16 @@ class AgentSessionController extends AbstractController
|
|||
return new JsonResponse(['message' => 'Client not found'], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
switch ($data['ostype']) {
|
||||
case 'Linux':
|
||||
$status = $client->getStatus();
|
||||
|
||||
switch ($status) {
|
||||
case ClientStatus::LINUX_SESSION:
|
||||
$client->setStatus(ClientStatus::LINUX);
|
||||
break;
|
||||
case 'Windows':
|
||||
case ClientStatus::WINDOWS_SESSION:
|
||||
$client->setStatus(ClientStatus::WINDOWS);
|
||||
break;
|
||||
case 'MacOS':
|
||||
case ClientStatus::MACOS_SESSION:
|
||||
$client->setStatus(ClientStatus::MACOS);
|
||||
break;
|
||||
|
||||
|
@ -187,7 +189,7 @@ class AgentSessionController extends AbstractController
|
|||
$this->logger->info('Client logged out', [
|
||||
'ip' => $data['ip'],
|
||||
'user' => $data['user'],
|
||||
'ostype' => $data['ostype'],
|
||||
'status' => $status,
|
||||
]);
|
||||
|
||||
return new JsonResponse([], Response::HTTP_OK);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Controller\OgAgent\Webhook;
|
||||
|
||||
use App\Controller\OgRepository\Image\CreateAuxFilesAction;
|
||||
|
@ -36,7 +38,9 @@ use Symfony\Contracts\HttpClient\HttpClientInterface;
|
|||
class StatusController extends AbstractController
|
||||
{
|
||||
const string CREATE_IMAGE = 'RESPUESTA_CrearImagen';
|
||||
const string CREATE_IMAGE_GIT = 'RESPUESTA_CrearImagenGit';
|
||||
const string RESTORE_IMAGE = 'RESPUESTA_RestaurarImagen';
|
||||
const string RESTORE_IMAGE_GIT = 'RESPUESTA_RestaurarImagenGit';
|
||||
const string CONFIGURE_IMAGE = 'RESPUESTA_Configurar';
|
||||
const string HARDWARE_INVENTORY = 'RESPUESTA_InventarioHardware';
|
||||
const string SOFTWARE_INVENTORY = 'RESPUESTA_InventarioSoftware';
|
||||
|
@ -65,7 +69,6 @@ class StatusController extends AbstractController
|
|||
|
||||
$this->logger->info('Webhook data received', $data);
|
||||
|
||||
// Esta parte del codigo nos indica si el cliente se encuentra activo
|
||||
if (isset($data['iph']) && isset($data['timestamp'])) {
|
||||
$client = $this->entityManager->getRepository(Client::class)->findOneBy(['ip' => $data['iph']]);
|
||||
if (!$client) {
|
||||
|
@ -81,11 +84,37 @@ class StatusController extends AbstractController
|
|||
if (isset($data['progress'])){
|
||||
$trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]);
|
||||
if ($trace){
|
||||
$trace->setProgress($data['progress'] * 100);
|
||||
$trace->setProgress((int)($data['progress'] * 100));
|
||||
$this->entityManager->persist($trace);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data['nfn']) && $data['nfn'] === self::CREATE_IMAGE_GIT) {
|
||||
$trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]);
|
||||
|
||||
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());
|
||||
} else {
|
||||
$trace->setStatus(TraceStatus::FAILED);
|
||||
$trace->setFinishedAt(new \DateTime());
|
||||
$trace->setOutput($data['der']);
|
||||
}
|
||||
|
||||
$client = $trace->getClient();
|
||||
$client->setStatus(ClientStatus::OG_LIVE);
|
||||
$this->entityManager->persist($client);
|
||||
$this->entityManager->persist($trace);
|
||||
$this->entityManager->flush();
|
||||
$this->logger->info('Git image creation completed.', ['job_id' => $data['job_id'], 'success' => $data['res'] === 1]);
|
||||
}
|
||||
|
||||
|
||||
if (isset($data['nfn']) && $data['nfn'] === self::CREATE_IMAGE) {
|
||||
$trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]);
|
||||
|
@ -142,7 +171,7 @@ class StatusController extends AbstractController
|
|||
$this->logger->info('Image updated. Success.', ['image' => (string) $imageImageRepository->getUuid()]);
|
||||
}
|
||||
|
||||
if (isset($data['nfn']) && ($data['nfn'] === self::RESTORE_IMAGE || $data['nfn'] === self::CONFIGURE_IMAGE)) {
|
||||
if (isset($data['nfn']) && ($data['nfn'] === self::RESTORE_IMAGE || $data['nfn'] === self::CONFIGURE_IMAGE || $data['nfn'] === self::RESTORE_IMAGE_GIT)) {
|
||||
$trace = $this->entityManager->getRepository(Trace::class)->findOneBy(['jobId' => $data['job_id']]);
|
||||
$client = $trace->getClient();
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ abstract class AbstractOgRepositoryController extends AbstractController
|
|||
'accept' => 'application/json',
|
||||
'Content-Type' => 'application/json'
|
||||
],
|
||||
'timeout' => 10,
|
||||
'timeout' => 30,
|
||||
]);
|
||||
|
||||
try {
|
||||
|
@ -56,7 +56,7 @@ abstract class AbstractOgRepositoryController extends AbstractController
|
|||
|
||||
return [
|
||||
'code' => Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
'error' => 'Client/Server error',
|
||||
'error' => $e->getMessage(),
|
||||
'details' => $e->getMessage(),
|
||||
];
|
||||
} catch (TransportExceptionInterface $e) {
|
||||
|
@ -64,7 +64,7 @@ abstract class AbstractOgRepositoryController extends AbstractController
|
|||
|
||||
return [
|
||||
'code' => Response::HTTP_INTERNAL_SERVER_ERROR,
|
||||
'error' => 'Transport error',
|
||||
'error' => $e->getMessage(),
|
||||
'details' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace App\Controller\OgRepository\Git;
|
|||
use App\Controller\OgRepository\AbstractOgRepositoryController;
|
||||
use App\Entity\Image;
|
||||
use App\Entity\ImageRepository;
|
||||
use App\Entity\GitRepository;
|
||||
use Symfony\Component\HttpKernel\Attribute\AsController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
@ -24,15 +25,16 @@ class CreateRepositoryAction extends AbstractOgRepositoryController
|
|||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function __invoke(Image $image, ImageRepository $repository): JsonResponse
|
||||
public function __invoke(GitRepository $gitRepository): JsonResponse
|
||||
{
|
||||
$params = [
|
||||
'json' => [
|
||||
'name' => $image->getName(),
|
||||
'name' => $gitRepository->getName(),
|
||||
'description' => $gitRepository->getDescription(),
|
||||
]
|
||||
];
|
||||
|
||||
$content = $this->createRequest('POST', 'http://'.$repository->getIp().':8006/ogrepository/v1/git/repositories', $params);
|
||||
$content = $this->createRequest('POST', 'http://'.$gitRepository->getRepository()->getIp().':8006/ogrepository/v1/git/repositories', $params);
|
||||
|
||||
if (isset($content['error']) && $content['code'] === Response::HTTP_INTERNAL_SERVER_ERROR ) {
|
||||
throw new BadRequestHttpException('Error creating repository');
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller\OgRepository\Git;
|
||||
|
||||
use App\Controller\OgRepository\AbstractOgRepositoryController;
|
||||
use App\Dto\Input\GetBranchesInput;
|
||||
use App\Entity\ImageRepository;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Attribute\AsController;
|
||||
use Symfony\Component\Validator\Exception\ValidatorException;
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
|
||||
#[AsController]
|
||||
class GetBranchesAction extends AbstractOgRepositoryController
|
||||
{
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function __invoke(ImageRepository $repository, GetBranchesInput $input): JsonResponse
|
||||
{
|
||||
$content = $this->createRequest('GET', 'http://'.$repository->getIp().':8006/ogrepository/v1/git/repositories/'.$input->repositoryName.'/branches');
|
||||
|
||||
if (isset($content['error']) && $content['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
|
||||
throw new \Exception('Error obteniendo branches del repositorio');
|
||||
}
|
||||
|
||||
return new JsonResponse(data: $content, status: Response::HTTP_OK);
|
||||
}
|
||||
}
|
|
@ -26,6 +26,10 @@ class GetCollectionAction extends AbstractOgRepositoryController
|
|||
{
|
||||
$content = $this->createRequest('GET', 'http://'.$data->getIp().':8006/ogrepository/v1/git/repositories');
|
||||
|
||||
if (isset($content['error']) && $content['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
|
||||
throw new \Exception('Error obteniendo commits del repositorio');
|
||||
}
|
||||
|
||||
return new JsonResponse(data: $content, status: Response::HTTP_OK);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller\OgRepository\Git;
|
||||
|
||||
use App\Controller\OgRepository\AbstractOgRepositoryController;
|
||||
use App\Dto\Input\GetCommitsInput;
|
||||
use App\Entity\ImageRepository;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Attribute\AsController;
|
||||
use Symfony\Component\Validator\Exception\ValidatorException;
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
|
||||
#[AsController]
|
||||
class GetCommitsAction extends AbstractOgRepositoryController
|
||||
{
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function __invoke(ImageRepository $repository, GetCommitsInput $input): JsonResponse
|
||||
{
|
||||
$content = $this->createRequest('GET', 'http://'.$repository->getIp().':8006/ogrepository/v1/git/repositories/'.$input->repositoryName.'/branches/'.$input->branch.'/commits');
|
||||
|
||||
if (isset($content['error']) && $content['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
|
||||
throw new \Exception('Error obteniendo commits del repositorio');
|
||||
}
|
||||
|
||||
return new JsonResponse(data: $content, status: Response::HTTP_OK);
|
||||
}
|
||||
}
|
|
@ -3,7 +3,8 @@
|
|||
namespace App\Controller\OgRepository\Git;
|
||||
|
||||
use App\Controller\OgRepository\AbstractOgRepositoryController;
|
||||
use App\Entity\GitImageRepository;
|
||||
use App\Entity\Image;
|
||||
use App\Entity\ImageRepository;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Attribute\AsController;
|
||||
|
@ -15,7 +16,7 @@ use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
|||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
|
||||
#[AsController]
|
||||
class GetTagsAction extends AbstractOgRepositoryController
|
||||
class GetRepositoriesAction extends AbstractOgRepositoryController
|
||||
{
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
|
@ -23,15 +24,12 @@ class GetTagsAction extends AbstractOgRepositoryController
|
|||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function __invoke(GitImageRepository $gitImageRepository): JsonResponse
|
||||
public function __invoke(ImageRepository $repository): JsonResponse
|
||||
{
|
||||
$repository = $gitImageRepository->getRepository();
|
||||
$image = $gitImageRepository->getImage();
|
||||
|
||||
$content = $this->createRequest('GET', 'http://'.$repository->getIp().':8006/ogrepository/v1/git/repositories/'.$image->getName().'/tags');
|
||||
$content = $this->createRequest('GET', 'http://'.$repository->getIp().':8006/ogrepository/v1/git/repositories');
|
||||
|
||||
if (isset($content['error']) && $content['code'] === Response::HTTP_INTERNAL_SERVER_ERROR ) {
|
||||
throw new BadRequestHttpException('Error getting tags');
|
||||
throw new BadRequestHttpException('Error getting repositories');
|
||||
}
|
||||
|
||||
return new JsonResponse(data: $content, status: Response::HTTP_OK);
|
|
@ -3,13 +3,11 @@
|
|||
namespace App\Controller\OgRepository\Git;
|
||||
|
||||
use App\Controller\OgRepository\AbstractOgRepositoryController;
|
||||
use App\Entity\GitImageRepository;
|
||||
use App\Entity\Image;
|
||||
use App\Entity\Client;
|
||||
use App\Entity\ImageRepository;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Attribute\AsController;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\Validator\Exception\ValidatorException;
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||||
|
@ -17,7 +15,7 @@ use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
|||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
|
||||
#[AsController]
|
||||
class CreateTagAction extends AbstractOgRepositoryController
|
||||
class SshKeyAction extends AbstractOgRepositoryController
|
||||
{
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
|
@ -25,23 +23,15 @@ class CreateTagAction extends AbstractOgRepositoryController
|
|||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function __invoke(Image $image, ImageRepository $repository, GitImageRepository $gitImageRepository): JsonResponse
|
||||
public function __invoke(ImageRepository $repository, Client $client): JsonResponse
|
||||
{
|
||||
$params = [
|
||||
$content = $this->createRequest('POST', 'http://'.$repository->getIp().':8006/ogrepository/v1/git/ssh_key', [
|
||||
'json' => [
|
||||
'commit' => "HEAD",
|
||||
'message' => $gitImageRepository->getVersion(),
|
||||
'name' => $image->getName(),
|
||||
]
|
||||
];
|
||||
'description' => $client->getName()->getOglive()->getName(),
|
||||
'oglive' => $client->getOglive()->getDirectory().'.iso',
|
||||
],
|
||||
]);
|
||||
|
||||
$content = $this->createRequest('POST', 'http://'.$repository->getIp().':8006/ogrepository/v1/git/repositories/'.
|
||||
$image->getName().'/tags', $params);
|
||||
|
||||
if (isset($content['error']) && $content['code'] === Response::HTTP_INTERNAL_SERVER_ERROR ) {
|
||||
throw new BadRequestHttpException('Error creating repository');
|
||||
}
|
||||
|
||||
return new JsonResponse(data: [], status: Response::HTTP_OK);
|
||||
return new JsonResponse(data: $content, status: Response::HTTP_OK);
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller\OgRepository\Git;
|
||||
|
||||
use App\Controller\OgRepository\AbstractOgRepositoryController;
|
||||
use App\Entity\GitImageRepository;
|
||||
use App\Entity\Image;
|
||||
use App\Entity\ImageImageRepository;
|
||||
use App\Entity\ImageRepository;
|
||||
use App\Model\ImageStatus;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
|
||||
class SyncAction extends AbstractOgRepositoryController
|
||||
{
|
||||
/**
|
||||
* @throws TransportExceptionInterface
|
||||
* @throws ServerExceptionInterface
|
||||
* @throws RedirectionExceptionInterface
|
||||
* @throws ClientExceptionInterface
|
||||
*/
|
||||
public function __invoke(ImageRepository $input): JsonResponse
|
||||
{
|
||||
$content = $this->createRequest('GET', 'http://' . $input->getIp() . ':8006/ogrepository/v1/git/repositories');
|
||||
|
||||
if (!isset($content['repositories'])) {
|
||||
return new JsonResponse(data: 'No repositories found', status: Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$repository = $this->entityManager->getRepository(GitImageRepository::class);
|
||||
|
||||
$existingRepositories = $repository->findBy(['imageRepository' => $input]);
|
||||
|
||||
foreach ($content['repositories'] as $repositoryData) {
|
||||
$gitImageRepositoryEntity = $repository->findOneBy([
|
||||
'imageRepository' => $input,
|
||||
'name' => $repositoryData
|
||||
]);
|
||||
|
||||
$imageEntity = $this->entityManager->getRepository(Image::class)->findOneBy(['name' => $repositoryData]);
|
||||
|
||||
if (!$imageEntity) {
|
||||
$imageEntity = new Image();
|
||||
$imageEntity->setName($repositoryData);
|
||||
$imageEntity->setRemotePc(false);
|
||||
$imageEntity->setIsGlobal(false);
|
||||
|
||||
$this->entityManager->persist($imageEntity);
|
||||
}
|
||||
|
||||
if (!$gitImageRepositoryEntity) {
|
||||
$gitImageRepositoryEntity = new GitImageRepository();
|
||||
$gitImageRepositoryEntity->setName($repositoryData);
|
||||
$gitImageRepositoryEntity->setStatus(ImageStatus::SUCCESS);
|
||||
$gitImageRepositoryEntity->setImageRepository($input);
|
||||
$gitImageRepositoryEntity->setImage($imageEntity);
|
||||
$gitImageRepositoryEntity->setBranch('main');
|
||||
$gitImageRepositoryEntity->setCreated(true);
|
||||
$gitImageRepositoryEntity->setCreatedAt(new \DateTime());
|
||||
|
||||
$this->entityManager->persist($gitImageRepositoryEntity);
|
||||
}
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
return new JsonResponse(data: $content, status: Response::HTTP_OK);
|
||||
}
|
||||
}
|
|
@ -35,6 +35,7 @@ class DeployImageAction extends AbstractOgRepositoryController
|
|||
$params = [
|
||||
'json' => [
|
||||
'ID_img' => $data->getImageFullsum(),
|
||||
//'image_name' => $data->getName(),
|
||||
'bitrate' => (string) $input->mcastSpeed.'M',
|
||||
'ip' => $input->mcastIp,
|
||||
'port' => $input->mcastPort,
|
||||
|
@ -54,6 +55,11 @@ class DeployImageAction extends AbstractOgRepositoryController
|
|||
|
||||
$content = $this->createRequest('POST', 'http://'.$repository->getIp().':8006/ogrepository/v1/'.$type, $params);
|
||||
|
||||
// Verificar si la respuesta contiene un error HTTP 500
|
||||
if (isset($content['code']) && $content['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
|
||||
throw new \Exception('Error del servidor OgRepository: ' . ($content['error'] ?? 'Error desconocido') . ' - ' . ($content['details'] ?? ''));
|
||||
}
|
||||
|
||||
return new JsonResponse(data: [], status: Response::HTTP_OK);
|
||||
}
|
||||
}
|
|
@ -62,6 +62,8 @@ class TransferAction extends AbstractOgRepositoryController
|
|||
|
||||
$inputData = [
|
||||
'imageName' => $image->getName(),
|
||||
'imageVersion' => $imageImageRepository->getVersion(),
|
||||
'imageCompleteName' => $imageImageRepository->getName(),
|
||||
'imageUuid' => $image->getUuid(),
|
||||
'imageImageRepositoryUuid' => $imageImageRepository->getUuid(),
|
||||
'repositoryUuid' => $repository->getUuid(),
|
||||
|
|
|
@ -92,9 +92,9 @@ class ResponseController extends AbstractOgRepositoryController
|
|||
$latestImageRepo = $this->entityManager->getRepository(ImageImageRepository::class)->findLatestVersionByImageAndRepository($image, $repository);
|
||||
|
||||
$newImageRepo = new ImageImageRepository();
|
||||
$newImageRepo->setName($image->getName().'_v'.($latestImageRepo ? $latestImageRepo->getVersion() + 1 : 1));
|
||||
$newImageRepo->setName($originImageImageRepository->getName());
|
||||
$newImageRepo->setImage($image);
|
||||
$newImageRepo->setVersion($latestImageRepo ? $latestImageRepo->getVersion() + 1 : 1);
|
||||
$newImageRepo->setVersion($originImageImageRepository->getVersion());
|
||||
$newImageRepo->setRepository($repository);
|
||||
$newImageRepo->setStatus(ImageStatus::SUCCESS);
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace App\Dto\Input;
|
||||
|
||||
use App\Dto\Output\TraceOutput;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
final class CancelMultipleTracesInput
|
||||
{
|
||||
/**
|
||||
* @var TraceOutput[]
|
||||
*/
|
||||
#[Assert\NotNull]
|
||||
#[Groups(['trace:write'])]
|
||||
public array $traces = [];
|
||||
}
|
|
@ -19,4 +19,7 @@ final class CommandExecuteInput
|
|||
#[Assert\NotNull]
|
||||
#[Groups(['command:write'])]
|
||||
public string $script = '';
|
||||
|
||||
#[Groups(['command:write'])]
|
||||
public bool $queue = false;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Dto\Input;
|
||||
|
||||
use ApiPlatform\Metadata\ApiProperty;
|
||||
use App\Dto\Output\ClientOutput;
|
||||
use App\Validator\Constraints\ClientsHaveSamePartitionCount;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
#[ClientsHaveSamePartitionCount]
|
||||
class DeployGitImageInput
|
||||
{
|
||||
#[Groups(['git-repository:write'])]
|
||||
#[ApiProperty(description: 'The type of the image deployment', example: "")]
|
||||
public ?string $type = 'git';
|
||||
|
||||
/**
|
||||
* @var ClientOutput[]
|
||||
*/
|
||||
#[Groups(['git-repository:write'])]
|
||||
#[ApiProperty(description: 'The clients to deploy the Git image to')]
|
||||
public ?array $clients = [];
|
||||
|
||||
#[Groups(['git-repository:write'])]
|
||||
#[ApiProperty(description: 'The disk number to deploy to', example: 1)]
|
||||
public ?int $diskNumber = null;
|
||||
|
||||
#[Groups(['git-repository:write'])]
|
||||
#[ApiProperty(description: 'The partition number to deploy to', example: 1)]
|
||||
public ?int $partitionNumber = null;
|
||||
|
||||
#[Groups(['git-repository:write'])]
|
||||
#[ApiProperty(description: 'The name of the Git repository', example: "my-git-repo")]
|
||||
public ?string $repositoryName = null;
|
||||
|
||||
#[Groups(['git-repository:write'])]
|
||||
#[ApiProperty(description: 'The Git branch to deploy', example: "main")]
|
||||
public ?string $branch = null;
|
||||
|
||||
#[Groups(['git-repository:write'])]
|
||||
#[ApiProperty(description: 'The Git commit hash (hexsha) to deploy', example: "a1b2c3d4e5f6")]
|
||||
public ?string $hexsha = null;
|
||||
|
||||
#[Groups(['git-repository:write'])]
|
||||
#[ApiProperty(description: 'Whether to queue the deployment', example: false)]
|
||||
public bool $queue = false;
|
||||
}
|
|
@ -4,8 +4,6 @@ namespace App\Dto\Input;
|
|||
|
||||
use ApiPlatform\Metadata\ApiProperty;
|
||||
use App\Dto\Output\ClientOutput;
|
||||
use App\Dto\Output\ImageOutput;
|
||||
use App\Dto\Output\PartitionOutput;
|
||||
use App\Validator\Constraints\ClientsHaveSamePartitionCount;
|
||||
use App\Validator\Constraints\OrganizationalUnitMulticastMode;
|
||||
use App\Validator\Constraints\OrganizationalUnitMulticastPort;
|
||||
|
@ -17,49 +15,63 @@ class DeployImageInput
|
|||
{
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
#[ApiProperty(description: 'The type of the image deployment', example: "")]
|
||||
public ?string $type = null;
|
||||
public ?string $type = 'monolithic';
|
||||
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
#[ApiProperty(description: 'The type of the image deployment', example: "")]
|
||||
#[ApiProperty(description: 'The deployment method', example: "unicast")]
|
||||
public ?string $method = null;
|
||||
|
||||
/**
|
||||
* @var ClientOutput[]
|
||||
*/
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
#[ApiProperty(description: 'The client to deploy the image')]
|
||||
#[ApiProperty(description: 'The clients to deploy the image to')]
|
||||
public ?array $clients = [];
|
||||
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
#[ApiProperty(description: 'The disk number to deploy to', example: 1)]
|
||||
public ?int $diskNumber = null;
|
||||
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
#[ApiProperty(description: 'The partition number to deploy to', example: 1)]
|
||||
public ?int $partitionNumber = null;
|
||||
|
||||
#[OrganizationalUnitP2PMode]
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
#[ApiProperty(description: 'P2P mode for torrent deployment', example: "seed")]
|
||||
public ?string $p2pMode = null;
|
||||
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
#[ApiProperty(description: 'P2P time for torrent deployment', example: 3600)]
|
||||
public ?int $p2pTime = null;
|
||||
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
#[ApiProperty(description: 'Multicast IP address', example: "239.255.255.250")]
|
||||
public ?string $mcastIp = null;
|
||||
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
#[ApiProperty(description: 'Multicast speed in Mbps', example: 100)]
|
||||
public ?int $mcastSpeed = null;
|
||||
|
||||
#[OrganizationalUnitMulticastPort]
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
#[ApiProperty(description: 'Multicast port', example: 8000)]
|
||||
public ?int $mcastPort = null;
|
||||
|
||||
#[OrganizationalUnitMulticastMode]
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
#[ApiProperty(description: 'Multicast mode', example: "full")]
|
||||
public ?string $mcastMode = null;
|
||||
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
#[ApiProperty(description: 'Maximum number of clients for multicast', example: 50)]
|
||||
public ?int $maxClients = null;
|
||||
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
#[ApiProperty(description: 'Maximum time for deployment in seconds', example: 3600)]
|
||||
public ?int $maxTime = null;
|
||||
}
|
||||
|
||||
#[Groups(['image-image-repository:write'])]
|
||||
#[ApiProperty(description: 'Whether to queue the deployment', example: false)]
|
||||
public bool $queue = false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace App\Dto\Input;
|
||||
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use OpenApi\Annotations as OA;
|
||||
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* description="Datos de entrada para obtener las branches de un repositorio Git",
|
||||
* required={"repositoryName"}
|
||||
* )
|
||||
*/
|
||||
final class GetBranchesInput
|
||||
{
|
||||
/**
|
||||
* @OA\Property(
|
||||
* description="Nombre del repositorio Git",
|
||||
* example="demo-oggit"
|
||||
* )
|
||||
*/
|
||||
#[Groups(['repository:write'])]
|
||||
#[Assert\NotBlank(message: 'El nombre del repositorio es requerido')]
|
||||
public ?string $repositoryName = null;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace App\Dto\Input;
|
||||
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use OpenApi\Annotations as OA;
|
||||
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* description="Datos de entrada para obtener los commits de un repositorio Git",
|
||||
* required={"repositoryName", "branch"}
|
||||
* )
|
||||
*/
|
||||
final class GetCommitsInput
|
||||
{
|
||||
/**
|
||||
* @OA\Property(
|
||||
* description="Nombre del repositorio Git",
|
||||
* example="demo-oggit"
|
||||
* )
|
||||
*/
|
||||
#[Groups(['repository:write'])]
|
||||
#[Assert\NotBlank(message: 'El nombre del repositorio es requerido')]
|
||||
public ?string $repositoryName = null;
|
||||
|
||||
/**
|
||||
* @OA\Property(
|
||||
* description="Nombre de la rama del repositorio",
|
||||
* example="main"
|
||||
* )
|
||||
*/
|
||||
#[Groups(['repository:write'])]
|
||||
#[Assert\NotBlank(message: 'El nombre de la rama es requerido')]
|
||||
public ?string $branch = null;
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Dto\Input;
|
||||
|
||||
use App\Entity\GitImageRepository;
|
||||
use App\Entity\ImageImageRepository;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
final class GitImageRepositoryInput
|
||||
{
|
||||
#[Groups(['git-image-repository:write'])]
|
||||
public ?string $description = '';
|
||||
|
||||
public function __construct(?GitImageRepository $gitImageRepository = null)
|
||||
{
|
||||
if (!$gitImageRepository) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->description = $gitImageRepository->getDescription();
|
||||
}
|
||||
|
||||
public function createOrUpdateEntity(?GitImageRepository $gitImageRepository = null): GitImageRepository
|
||||
{
|
||||
if (!$gitImageRepository) {
|
||||
$gitImageRepository = new GitImageRepository();
|
||||
}
|
||||
|
||||
$gitImageRepository->setDescription($this->description);
|
||||
|
||||
return $gitImageRepository;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
namespace App\Dto\Input;
|
||||
|
||||
use App\Entity\GitRepository;
|
||||
use App\Repository\ImageRepositoryRepository;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use OpenApi\Annotations as OA;
|
||||
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* description="Datos de entrada para crear o actualizar un repositorio Git",
|
||||
* required={"name", "repository"}
|
||||
* )
|
||||
*/
|
||||
final class GitRepositoryInput
|
||||
{
|
||||
/**
|
||||
* @OA\Property(
|
||||
* description="Nombre del repositorio Git",
|
||||
* example="mi-repositorio"
|
||||
* )
|
||||
*/
|
||||
#[Groups(['git-repository:write'])]
|
||||
#[Assert\NotBlank(message: 'El nombre del repositorio es requerido')]
|
||||
public ?string $name = null;
|
||||
|
||||
/**
|
||||
* @OA\Property(
|
||||
* description="Descripción del repositorio",
|
||||
* example="Repositorio para el proyecto principal"
|
||||
* )
|
||||
*/
|
||||
#[Groups(['git-repository:write'])]
|
||||
public ?string $description = null;
|
||||
|
||||
/**
|
||||
* @OA\Property(
|
||||
* description="ID del ImageRepository donde se creará el repositorio",
|
||||
* example=1
|
||||
* )
|
||||
*/
|
||||
#[Groups(['git-repository:write'])]
|
||||
#[Assert\NotNull(message: 'El ID del ImageRepository es requerido')]
|
||||
#[Assert\Type(type: 'integer', message: 'El ID del ImageRepository debe ser un número entero')]
|
||||
public ?int $repository = null; // Ahora es el ID del ImageRepository
|
||||
|
||||
public function __construct(?GitRepository $gitRepository = null)
|
||||
{
|
||||
if (!$gitRepository) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->name = $gitRepository->getName();
|
||||
$this->description = $gitRepository->getDescription();
|
||||
$this->repository = $gitRepository->getRepository()?->getId();
|
||||
}
|
||||
|
||||
public function createOrUpdateEntity(?GitRepository $gitRepository = null): GitRepository
|
||||
{
|
||||
if (!$gitRepository) {
|
||||
$gitRepository = new GitRepository();
|
||||
}
|
||||
|
||||
$gitRepository->setName($this->name);
|
||||
$gitRepository->setDescription($this->description);
|
||||
|
||||
return $gitRepository;
|
||||
}
|
||||
}
|
|
@ -21,7 +21,6 @@ use Symfony\Component\Validator\Constraints as Assert;
|
|||
|
||||
final class ImageInput
|
||||
{
|
||||
#[Assert\NotBlank(message: 'validators.image.name.not_blank')]
|
||||
#[Groups(['image:write'])]
|
||||
#[ApiProperty(description: 'The name of the image', example: "Image 1")]
|
||||
public ?string $name = null;
|
||||
|
@ -73,6 +72,14 @@ final class ImageInput
|
|||
#[ApiProperty(description: 'The global property of the image')]
|
||||
public ?bool $isGlobal = false;
|
||||
|
||||
#[Groups(['image:write'])]
|
||||
#[ApiProperty(description: 'The queue property of the image')]
|
||||
public bool $queue = false;
|
||||
|
||||
#[Groups(['image:write'])]
|
||||
#[ApiProperty(description: 'The name of the Git repository to use for this image', example: "mi-repositorio")]
|
||||
public ?string $gitRepository = null;
|
||||
|
||||
public function __construct(?Image $image = null)
|
||||
{
|
||||
if (!$image) {
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
namespace App\Dto\Input;
|
||||
|
||||
use ApiPlatform\Metadata\ApiProperty;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
final class KillJobInput
|
||||
{
|
||||
#[Assert\NotNull()]
|
||||
#[Groups(['trace:write'])]
|
||||
#[ApiProperty(description: 'The job id to kill', example: "1234567890")]
|
||||
public string $jobId;
|
||||
}
|
|
@ -12,5 +12,8 @@ final class MultipleClientsInput
|
|||
*/
|
||||
#[Groups(['client:write'])]
|
||||
public array $clients = [];
|
||||
|
||||
#[Groups(['client:write'])]
|
||||
public bool $queue = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,5 +18,8 @@ final class PartitionPostInput
|
|||
*/
|
||||
#[Groups(['partition:write'])]
|
||||
public array $clients = [];
|
||||
|
||||
#[Groups(['partition:write'])]
|
||||
public bool $queue = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Dto\Output;
|
||||
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use App\Entity\GitImageRepository;
|
||||
use App\Entity\ImageImageRepository;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
|
||||
#[Get(shortName: 'GitImageRepository')]
|
||||
final class GitImageRepositoryOutput extends AbstractOutput
|
||||
{
|
||||
#[Groups(['git-image-repository:read', 'image:read'])]
|
||||
public ?ImageOutput $image = null;
|
||||
|
||||
#[Groups(['git-image-repository:read', 'image:read'])]
|
||||
public ?ImageRepositoryOutput $imageRepository = null;
|
||||
|
||||
#[Groups(['git-image-repository:read', 'image:read'])]
|
||||
public string $status = '';
|
||||
|
||||
#[Groups(['git-image-repository:read', 'image:read'])]
|
||||
public ?string $description = '';
|
||||
|
||||
#[Groups(['git-image-repository:read', 'image:read'])]
|
||||
public string $name = '';
|
||||
|
||||
#[Groups(['git-image-repository:read', 'image:read'])]
|
||||
public ?string $branch = '';
|
||||
|
||||
#[Groups(['git-image-repository:read', 'image:read'])]
|
||||
public ?string $tag = '';
|
||||
|
||||
#[Groups(['git-image-repository:read', 'image:read'])]
|
||||
public \DateTime $createdAt;
|
||||
|
||||
#[Groups(['git-image-repository:read', 'image:read'])]
|
||||
public ?string $createdBy = null;
|
||||
|
||||
public function __construct(GitImageRepository $gitImageRepository, array $context = [])
|
||||
{
|
||||
parent::__construct($gitImageRepository);
|
||||
|
||||
if (isset($context['groups']) && in_array('git-image-repository:read', $context['groups'])) {
|
||||
if ($gitImageRepository->getImage()) {
|
||||
$this->image = new ImageOutput($gitImageRepository->getImage());
|
||||
}
|
||||
}
|
||||
|
||||
if ($gitImageRepository->getRepository()) {
|
||||
$this->imageRepository = new ImageRepositoryOutput($gitImageRepository->getRepository());
|
||||
}
|
||||
|
||||
$this->name = $gitImageRepository->getName();
|
||||
$this->description = $gitImageRepository->getDescription();
|
||||
$this->status = $gitImageRepository->getStatus();
|
||||
$this->branch = $gitImageRepository->getBranch();
|
||||
$this->tag = $gitImageRepository->getTag();
|
||||
$this->createdAt = $gitImageRepository->getCreatedAt();
|
||||
$this->createdBy = $gitImageRepository->getCreatedBy();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
|
||||
namespace App\Dto\Output;
|
||||
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use App\Entity\GitRepository;
|
||||
use Symfony\Component\Serializer\Annotation\Groups;
|
||||
use OpenApi\Annotations as OA;
|
||||
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* description="Datos de salida de un repositorio Git"
|
||||
* )
|
||||
*/
|
||||
#[Get(shortName: 'GitRepository')]
|
||||
final class GitRepositoryOutput
|
||||
{
|
||||
/**
|
||||
* @OA\Property(
|
||||
* description="UUID del repositorio Git",
|
||||
* example="123e4567-e89b-12d3-a456-426614174000"
|
||||
* )
|
||||
*/
|
||||
#[Groups(['git-repository:read', 'git-image-repository:read'])]
|
||||
public string $uuid = '';
|
||||
|
||||
/**
|
||||
* @OA\Property(
|
||||
* description="ID del repositorio Git",
|
||||
* example=1
|
||||
* )
|
||||
*/
|
||||
#[Groups(['git-repository:read', 'git-image-repository:read'])]
|
||||
public int $id = 0;
|
||||
|
||||
/**
|
||||
* @OA\Property(
|
||||
* description="Nombre del repositorio Git",
|
||||
* example="mi-repositorio"
|
||||
* )
|
||||
*/
|
||||
#[Groups(['git-repository:read', 'git-image-repository:read'])]
|
||||
public string $name = '';
|
||||
|
||||
/**
|
||||
* @OA\Property(
|
||||
* description="Descripción del repositorio",
|
||||
* example="Repositorio para el proyecto principal"
|
||||
* )
|
||||
*/
|
||||
#[Groups(['git-repository:read', 'git-image-repository:read'])]
|
||||
public ?string $description = '';
|
||||
|
||||
/**
|
||||
* @OA\Property(
|
||||
* description="Servidor donde se encuentra el repositorio",
|
||||
* example={"id": 1, "name": "Servidor Principal", "ip": "192.168.1.100"}
|
||||
* )
|
||||
*/
|
||||
#[Groups(['git-repository:read', 'git-image-repository:read'])]
|
||||
public ?ImageRepositoryOutput $repository = null;
|
||||
|
||||
/**
|
||||
* @OA\Property(
|
||||
* description="Fecha de creación del repositorio",
|
||||
* example="2024-01-01T00:00:00+00:00"
|
||||
* )
|
||||
*/
|
||||
#[Groups(['git-repository:read', 'git-image-repository:read'])]
|
||||
public ?\DateTime $createdAt = null;
|
||||
|
||||
/**
|
||||
* @OA\Property(
|
||||
* description="Usuario que creó el repositorio",
|
||||
* example="admin"
|
||||
* )
|
||||
*/
|
||||
#[Groups(['git-repository:read', 'git-image-repository:read'])]
|
||||
public ?string $createdBy = null;
|
||||
|
||||
public function __construct(GitRepository $gitRepository, array $context = [])
|
||||
{
|
||||
if ($gitRepository->getId()) {
|
||||
$this->uuid = $gitRepository->getUuid()->toString();
|
||||
$this->id = $gitRepository->getId();
|
||||
} else {
|
||||
$this->uuid = $gitRepository->getUuid()->toString();
|
||||
$this->id = 0;
|
||||
}
|
||||
|
||||
$this->name = $gitRepository->getName();
|
||||
$this->description = $gitRepository->getDescription();
|
||||
|
||||
if ($gitRepository->getRepository()) {
|
||||
$this->repository = new ImageRepositoryOutput($gitRepository->getRepository());
|
||||
}
|
||||
|
||||
$this->createdAt = $gitRepository->getCreatedAt() ?: new \DateTime();
|
||||
$this->createdBy = $gitRepository->getCreatedBy();
|
||||
}
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\GitImageRepositoryRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: GitImageRepositoryRepository::class)]
|
||||
class GitImageRepository extends AbstractEntity
|
||||
{
|
||||
use NameableTrait;
|
||||
|
||||
#[ORM\ManyToOne(inversedBy: 'gitImageRepositories')]
|
||||
#[ORM\JoinColumn(nullable: false)]
|
||||
private ?Image $image = null;
|
||||
|
||||
#[ORM\ManyToOne(inversedBy: 'gitImageRepositories')]
|
||||
private ?ImageRepository $repository = null;
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
private ?string $status = null;
|
||||
|
||||
#[ORM\Column(length: 255, nullable: true)]
|
||||
private ?string $description = null;
|
||||
|
||||
#[ORM\Column(length: 255, nullable: true)]
|
||||
private ?string $branch = null;
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
private ?string $tag = null;
|
||||
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?int $version = null;
|
||||
|
||||
#[ORM\Column]
|
||||
private ?bool $created = null;
|
||||
|
||||
|
||||
public function getImage(): ?Image
|
||||
{
|
||||
return $this->image;
|
||||
}
|
||||
|
||||
public function setImage(?Image $image): static
|
||||
{
|
||||
$this->image = $image;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStatus(): ?string
|
||||
{
|
||||
return $this->status;
|
||||
}
|
||||
|
||||
public function setStatus(string $status): static
|
||||
{
|
||||
$this->status = $status;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription(): ?string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription(?string $description): static
|
||||
{
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBranch(): ?string
|
||||
{
|
||||
return $this->branch;
|
||||
}
|
||||
|
||||
public function setBranch(?string $branch): static
|
||||
{
|
||||
$this->branch = $branch;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTag(): ?string
|
||||
{
|
||||
return $this->tag;
|
||||
}
|
||||
|
||||
public function setTag(?string $tag): static
|
||||
{
|
||||
$this->tag = $tag;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getVersion(): ?int
|
||||
{
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
public function setVersion(?int $version): static
|
||||
{
|
||||
$this->version = $version;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isCreated(): ?bool
|
||||
{
|
||||
return $this->created;
|
||||
}
|
||||
|
||||
public function setCreated(bool $created): static
|
||||
{
|
||||
$this->created = $created;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRepository(): ?ImageRepository
|
||||
{
|
||||
return $this->repository;
|
||||
}
|
||||
|
||||
public function setRepository(?ImageRepository $imageRepository): static
|
||||
{
|
||||
$this->repository = $imageRepository;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\GitRepositoryRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use App\Entity\AbstractEntity;
|
||||
|
||||
#[ORM\Entity(repositoryClass: GitRepositoryRepository::class)]
|
||||
class GitRepository extends AbstractEntity
|
||||
{
|
||||
use NameableTrait;
|
||||
|
||||
#[ORM\Column(length: 255, nullable: true)]
|
||||
private ?string $description = null;
|
||||
|
||||
#[ORM\ManyToOne(inversedBy: 'gitRepositories')]
|
||||
private ?ImageRepository $repository = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
||||
public function getDescription(): ?string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription(?string $description): static
|
||||
{
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRepository(): ?ImageRepository
|
||||
{
|
||||
return $this->repository;
|
||||
}
|
||||
|
||||
public function setRepository(?ImageRepository $repository): static
|
||||
{
|
||||
$this->repository = $repository;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -43,12 +43,6 @@ class Image extends AbstractEntity
|
|||
#[ORM\Column(nullable: true)]
|
||||
private ?int $version = null;
|
||||
|
||||
/**
|
||||
* @var Collection<int, GitImageRepository>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'image', targetEntity: GitImageRepository::class,cascade: ['persist'], orphanRemoval: true)]
|
||||
private Collection $gitImageRepositories;
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
private ?string $type = null;
|
||||
|
||||
|
@ -56,7 +50,6 @@ class Image extends AbstractEntity
|
|||
{
|
||||
parent::__construct();
|
||||
$this->imageImageRepositories = new ArrayCollection();
|
||||
$this->gitImageRepositories = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getSoftwareProfile(): ?SoftwareProfile
|
||||
|
@ -187,36 +180,6 @@ class Image extends AbstractEntity
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, GitImageRepository>
|
||||
*/
|
||||
public function getGitImageRepositories(): Collection
|
||||
{
|
||||
return $this->gitImageRepositories;
|
||||
}
|
||||
|
||||
public function addGitImageRepository(GitImageRepository $gitImageRepository): static
|
||||
{
|
||||
if (!$this->gitImageRepositories->contains($gitImageRepository)) {
|
||||
$this->gitImageRepositories->add($gitImageRepository);
|
||||
$gitImageRepository->setImage($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeGitImageRepository(GitImageRepository $gitImageRepository): static
|
||||
{
|
||||
if ($this->gitImageRepositories->removeElement($gitImageRepository)) {
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($gitImageRepository->getImage() === $this) {
|
||||
$gitImageRepository->setImage(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getType(): ?string
|
||||
{
|
||||
return $this->type;
|
||||
|
|
|
@ -32,17 +32,10 @@ class ImageRepository extends AbstractEntity
|
|||
#[ORM\Column(length: 255, nullable: true)]
|
||||
private ?string $sshPort = null;
|
||||
|
||||
/**
|
||||
* @var Collection<int, GitImageRepository>
|
||||
*/
|
||||
#[ORM\OneToMany(mappedBy: 'repository', targetEntity: GitImageRepository::class)]
|
||||
private Collection $gitImageRepositories;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->imageImageRepositories = new ArrayCollection();
|
||||
$this->gitImageRepositories = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getIp(): ?string
|
||||
|
@ -122,34 +115,4 @@ class ImageRepository extends AbstractEntity
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, GitImageRepository>
|
||||
*/
|
||||
public function getGitImageRepositories(): Collection
|
||||
{
|
||||
return $this->gitImageRepositories;
|
||||
}
|
||||
|
||||
public function addGitImageRepository(GitImageRepository $gitImageRepository): static
|
||||
{
|
||||
if (!$this->gitImageRepositories->contains($gitImageRepository)) {
|
||||
$this->gitImageRepositories->add($gitImageRepository);
|
||||
$gitImageRepository->setImageRepository($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeGitImageRepository(GitImageRepository $gitImageRepository): static
|
||||
{
|
||||
if ($this->gitImageRepositories->removeElement($gitImageRepository)) {
|
||||
// set the owning side to null (unless already changed)
|
||||
if ($gitImageRepository->getImageRepository() === $this) {
|
||||
$gitImageRepository->setImageRepository(null);
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,9 @@ readonly class ClientMacListener
|
|||
return;
|
||||
}
|
||||
|
||||
$this->putHostAction->__invoke($oldMac, $client);
|
||||
$this->deleteAction->__invoke($oldMac);
|
||||
if ($client->getSubnet()) {
|
||||
$this->putHostAction->__invoke($oldMac, $client);
|
||||
$this->deleteAction->__invoke($oldMac);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ final class CommandTypes
|
|||
public const string DEPLOY_IMAGE = 'deploy-image';
|
||||
public const string RESTORE_IMAGE = 'restore-image';
|
||||
public const string CREATE_IMAGE = 'create-image';
|
||||
public const string CREATE_IMAGE_GIT = 'create-image-git';
|
||||
public const string CONVERT_IMAGE = 'convert-image';
|
||||
public const string CREATE_IMAGE_AUX_FILE = 'create-image-aux-file';
|
||||
public const string BACKUP_IMAGE = 'backup-image';
|
||||
|
@ -26,11 +27,13 @@ final class CommandTypes
|
|||
public const string REMOVE_CACHE_IMAGE = 'remove-cache-image';
|
||||
public const string HARDWARE_INVENTORY = 'hardware-inventory';
|
||||
public const string SOFTWARE_INVENTORY = 'software-inventory';
|
||||
public const string KILL_JOB = 'kill-job';
|
||||
|
||||
private const array COMMAND_TYPES = [
|
||||
self::DEPLOY_IMAGE => 'Deploy Image',
|
||||
self::RESTORE_IMAGE => 'Update Cache',
|
||||
self::CREATE_IMAGE => 'Create Image',
|
||||
self::CREATE_IMAGE_GIT => 'Create Image Git',
|
||||
self::CONVERT_IMAGE => 'Convert Image',
|
||||
self::CONVERT_IMAGE_TO_VIRTUAL => 'Convert Image to Virtual',
|
||||
self::CREATE_IMAGE_AUX_FILE => 'Create Image Aux File',
|
||||
|
@ -50,6 +53,7 @@ final class CommandTypes
|
|||
self::REMOVE_CACHE_IMAGE => 'Remove Cache Image',
|
||||
self::HARDWARE_INVENTORY => 'Hardware Inventory',
|
||||
self::SOFTWARE_INVENTORY => 'Software Inventory',
|
||||
self::KILL_JOB => 'Kill Job',
|
||||
];
|
||||
|
||||
public static function getCommandTypes(): array
|
||||
|
|
|
@ -12,11 +12,13 @@ final class DeployMethodTypes
|
|||
public const string UNICAST = 'unicast';
|
||||
public const string UNICAST_DIRECT = 'unicast-direct';
|
||||
public const string TORRENT = 'p2p';
|
||||
public const string GIT = 'git';
|
||||
|
||||
private const array DEPLOYMENT_METHOD_TYPES = [
|
||||
self::MULTICAST => 'Multicast',
|
||||
self::UNICAST => 'Unicast',
|
||||
self::TORRENT => 'Torrent',
|
||||
self::GIT => 'Git',
|
||||
];
|
||||
|
||||
public static function getDeploymentMethodTypes(): array
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\GitImageRepository;
|
||||
use App\Entity\Image;
|
||||
use App\Entity\ImageRepository as Repository;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<GitImageRepository>
|
||||
*/
|
||||
class GitImageRepositoryRepository extends AbstractRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, GitImageRepository::class);
|
||||
}
|
||||
|
||||
public function findLatestVersionByImageAndRepository(Image $image, Repository $repository): ?GitImageRepository
|
||||
{
|
||||
return $this->createQueryBuilder('i')
|
||||
->andWhere('i.image = :imageId')
|
||||
->setParameter('imageId', $image->getId())
|
||||
->andWhere('i.repository = :repository')
|
||||
->setParameter('repository', $repository->getId())
|
||||
->orderBy('i.version', 'DESC')
|
||||
->setMaxResults(1)
|
||||
->getQuery()
|
||||
->getOneOrNullResult();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\GitRepository;
|
||||
use App\Repository\AbstractRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<GitRepository>
|
||||
*/
|
||||
class GitRepositoryRepository extends AbstractRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, GitRepository::class);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Entity\GitRepository;
|
||||
use App\Entity\ImageRepository;
|
||||
use App\Controller\OgRepository\Git\GetCollectionAction;
|
||||
use App\Controller\OgRepository\Git\CreateRepositoryAction;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class ExternalGitRepositoryService
|
||||
{
|
||||
public function __construct(
|
||||
private HttpClientInterface $httpClient,
|
||||
private GetCollectionAction $getCollectionAction,
|
||||
private CreateRepositoryAction $createRepositoryAction
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Obtiene todos los repositorios de un servidor externo
|
||||
*/
|
||||
public function getRepositories(ImageRepository $imageRepository): array
|
||||
{
|
||||
try {
|
||||
$response = $this->getCollectionAction->__invoke($imageRepository);
|
||||
$content = json_decode($response->getContent(), true);
|
||||
|
||||
if ($response->getStatusCode() !== Response::HTTP_OK) {
|
||||
throw new BadRequestHttpException('Error obteniendo repositorios del servidor externo');
|
||||
}
|
||||
|
||||
// El GetCollectionAction devuelve directamente el contenido de la API externa
|
||||
if (!isset($content['repositories'])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $content['repositories'];
|
||||
} catch (\Exception $e) {
|
||||
throw new BadRequestHttpException('Error obteniendo repositorios: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtiene un repositorio específico por nombre
|
||||
*/
|
||||
public function getRepository(string $name, ImageRepository $imageRepository): ?array
|
||||
{
|
||||
$repositories = $this->getRepositories($imageRepository);
|
||||
|
||||
foreach ($repositories as $repo) {
|
||||
// La API externa devuelve los nombres como strings simples
|
||||
if ($repo === $name) {
|
||||
return ['name' => $repo];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea un repositorio en el servidor externo
|
||||
*/
|
||||
public function createRepository(GitRepository $gitRepository): array
|
||||
{
|
||||
try {
|
||||
$response = $this->createRepositoryAction->__invoke($gitRepository);
|
||||
|
||||
if ($response->getStatusCode() !== Response::HTTP_OK) {
|
||||
throw new BadRequestHttpException('Error creando repositorio en el servidor externo');
|
||||
}
|
||||
|
||||
// El CreateRepositoryAction devuelve un array vacío en caso de éxito
|
||||
return json_decode($response->getContent(), true) ?: [];
|
||||
} catch (\Exception $e) {
|
||||
throw new BadRequestHttpException('Error creando repositorio: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualiza un repositorio en el servidor externo
|
||||
*/
|
||||
public function updateRepository(GitRepository $gitRepository): array
|
||||
{
|
||||
$response = $this->httpClient->request('PUT',
|
||||
"http://{$gitRepository->getRepository()->getIp()}:8006/ogrepository/v1/git/repositories/{$gitRepository->getName()}",
|
||||
[
|
||||
'json' => [
|
||||
'name' => $gitRepository->getName(),
|
||||
'description' => $gitRepository->getDescription(),
|
||||
]
|
||||
]
|
||||
);
|
||||
|
||||
if ($response->getStatusCode() !== Response::HTTP_OK) {
|
||||
throw new BadRequestHttpException('Error actualizando repositorio en el servidor externo');
|
||||
}
|
||||
|
||||
return $response->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Elimina un repositorio del servidor externo
|
||||
*/
|
||||
public function deleteRepository(string $name, ImageRepository $imageRepository): void
|
||||
{
|
||||
$response = $this->httpClient->request('DELETE',
|
||||
"http://{$imageRepository->getIp()}:8006/ogrepository/v1/git/repositories/{$name}"
|
||||
);
|
||||
|
||||
if ($response->getStatusCode() !== Response::HTTP_OK) {
|
||||
throw new BadRequestHttpException('Error eliminando repositorio del servidor externo');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convierte datos de la API externa a una entidad GitRepository
|
||||
*/
|
||||
public function createEntityFromExternalData($externalData, ImageRepository $imageRepository): GitRepository
|
||||
{
|
||||
$gitRepository = new GitRepository();
|
||||
|
||||
// La API externa devuelve los nombres como strings simples
|
||||
if (is_string($externalData)) {
|
||||
$gitRepository->setName($externalData);
|
||||
} elseif (is_array($externalData) && isset($externalData['name'])) {
|
||||
$gitRepository->setName($externalData['name']);
|
||||
$gitRepository->setDescription($externalData['description'] ?? null);
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Los datos externos deben ser string o array con nombre');
|
||||
}
|
||||
|
||||
$gitRepository->setRepository($imageRepository);
|
||||
|
||||
return $gitRepository;
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\State\Processor;
|
||||
|
||||
use ApiPlatform\Metadata\Delete;
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use ApiPlatform\Metadata\Patch;
|
||||
use ApiPlatform\Metadata\Post;
|
||||
use ApiPlatform\Metadata\Put;
|
||||
use ApiPlatform\State\ProcessorInterface;
|
||||
use ApiPlatform\Validator\ValidatorInterface;
|
||||
use App\Dto\Input\GitImageRepositoryInput;
|
||||
use App\Dto\Output\GitImageRepositoryOutput;
|
||||
use App\Repository\GitImageRepositoryRepository;
|
||||
|
||||
readonly class GitImageRepositoryProcessor implements ProcessorInterface
|
||||
{
|
||||
public function __construct(
|
||||
private GitImageRepositoryRepository $imageRepository,
|
||||
private ValidatorInterface $validator,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): GitImageRepositoryOutput|null
|
||||
{
|
||||
switch ($operation){
|
||||
case $operation instanceof Post:
|
||||
case $operation instanceof Put:
|
||||
case $operation instanceof Patch:
|
||||
return $this->processCreateOrUpdate($data, $operation, $uriVariables, $context);
|
||||
case $operation instanceof Delete:
|
||||
return $this->processDelete($data, $operation, $uriVariables, $context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): GitImageRepositoryOutput
|
||||
{
|
||||
if (!($data instanceof GitImageRepositoryInput)) {
|
||||
throw new \Exception(sprintf('data is not instance of %s', GitImageRepositoryInput::class));
|
||||
}
|
||||
|
||||
$entity = null;
|
||||
if (isset($uriVariables['uuid'])) {
|
||||
$entity = $this->imageRepository->findOneByUuid($uriVariables['uuid']);
|
||||
}
|
||||
|
||||
$image = $data->createOrUpdateEntity($entity);
|
||||
$this->validator->validate($image);
|
||||
$this->imageRepository->save($image);
|
||||
|
||||
return new GitImageRepositoryOutput($image);
|
||||
}
|
||||
|
||||
private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null
|
||||
{
|
||||
$user = $this->imageRepository->findOneByUuid($uriVariables['uuid']);
|
||||
$this->imageRepository->delete($user);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
namespace App\State\Processor;
|
||||
|
||||
use ApiPlatform\Metadata\Delete;
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use ApiPlatform\Metadata\Patch;
|
||||
use ApiPlatform\Metadata\Post;
|
||||
use ApiPlatform\Metadata\Put;
|
||||
use ApiPlatform\State\ProcessorInterface;
|
||||
use ApiPlatform\Validator\ValidatorInterface;
|
||||
use App\Dto\Input\GitRepositoryInput;
|
||||
use App\Dto\Output\GitRepositoryOutput;
|
||||
use App\Service\ExternalGitRepositoryService;
|
||||
use App\Repository\ImageRepositoryRepository;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
|
||||
readonly class GitRepositoryProcessor implements ProcessorInterface
|
||||
{
|
||||
public function __construct(
|
||||
private ExternalGitRepositoryService $externalService,
|
||||
private ImageRepositoryRepository $imageRepositoryRepository,
|
||||
private ValidatorInterface $validator,
|
||||
private RequestStack $requestStack,
|
||||
private KernelInterface $kernel
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): GitRepositoryOutput|null
|
||||
{
|
||||
switch ($operation){
|
||||
case $operation instanceof Post:
|
||||
case $operation instanceof Put:
|
||||
case $operation instanceof Patch:
|
||||
return $this->processCreateOrUpdate($data, $operation, $uriVariables, $context);
|
||||
case $operation instanceof Delete:
|
||||
return $this->processDelete($data, $operation, $uriVariables, $context);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): GitRepositoryOutput
|
||||
{
|
||||
if (!($data instanceof GitRepositoryInput)) {
|
||||
throw new \Exception(sprintf('data is not instance of %s', GitRepositoryInput::class));
|
||||
}
|
||||
|
||||
// Obtener el repositoryId del input data
|
||||
$repositoryId = $data->repository;
|
||||
|
||||
if (!$repositoryId) {
|
||||
throw new \InvalidArgumentException('El campo "repository" es requerido');
|
||||
}
|
||||
|
||||
$imageRepository = $this->imageRepositoryRepository->find($repositoryId);
|
||||
if (!$imageRepository) {
|
||||
throw new \Exception('ImageRepository no encontrado');
|
||||
}
|
||||
|
||||
$gitRepository = $data->createOrUpdateEntity();
|
||||
$gitRepository->setRepository($imageRepository);
|
||||
|
||||
$this->validator->validate($gitRepository);
|
||||
|
||||
if ($this->kernel->getEnvironment() !== 'test') {
|
||||
try {
|
||||
if ($operation instanceof Post) {
|
||||
$this->externalService->createRepository($gitRepository);
|
||||
} else {
|
||||
$this->externalService->updateRepository($gitRepository);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
throw new \Exception('Error en operación con API externa: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return new GitRepositoryOutput($gitRepository);
|
||||
}
|
||||
|
||||
private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null
|
||||
{
|
||||
// Obtener el ImageRepository desde los parámetros
|
||||
$request = $this->requestStack->getCurrentRequest();
|
||||
$repositoryId = $request->query->get('repository');
|
||||
$name = $uriVariables['name'];
|
||||
|
||||
if (!$repositoryId || !$name) {
|
||||
throw new \InvalidArgumentException('Los parámetros "repository" y "name" son requeridos');
|
||||
}
|
||||
|
||||
$imageRepository = $this->imageRepositoryRepository->find($repositoryId);
|
||||
if (!$imageRepository) {
|
||||
throw new \Exception('ImageRepository no encontrado');
|
||||
}
|
||||
|
||||
if ($this->kernel->getEnvironment() !== 'test') {
|
||||
try {
|
||||
$this->externalService->deleteRepository($name, $imageRepository);
|
||||
} catch (\Exception $e) {
|
||||
throw new \Exception('Error eliminando repositorio en API externa: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -12,12 +12,14 @@ use ApiPlatform\Validator\ValidatorInterface;
|
|||
use App\Dto\Input\ImageImageRepositoryInput;
|
||||
use App\Dto\Output\ImageImageRepositoryOutput;
|
||||
use App\Repository\ImageImageRepositoryRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
readonly class ImageImageRepositoryProcessor implements ProcessorInterface
|
||||
{
|
||||
public function __construct(
|
||||
private ImageImageRepositoryRepository $imageRepository,
|
||||
private ValidatorInterface $validator,
|
||||
private EntityManagerInterface $entityManager
|
||||
)
|
||||
{
|
||||
}
|
||||
|
@ -60,8 +62,18 @@ readonly class ImageImageRepositoryProcessor implements ProcessorInterface
|
|||
|
||||
private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null
|
||||
{
|
||||
$user = $this->imageRepository->findOneByUuid($uriVariables['uuid']);
|
||||
$this->imageRepository->delete($user);
|
||||
$imageImageRepository = $this->imageRepository->findOneByUuid($uriVariables['uuid']);
|
||||
$this->imageRepository->delete($imageImageRepository);
|
||||
|
||||
$repository = $imageImageRepository->getRepository();
|
||||
$image = $imageImageRepository->getImage();
|
||||
|
||||
$imageImageCollection = $image->getImageImageRepositories();
|
||||
|
||||
if ($imageImageCollection->isEmpty()) {
|
||||
$this->entityManager->remove($image);
|
||||
$this->entityManager->flush();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@ use App\Repository\ImageRepository;
|
|||
use App\Repository\ImageRepositoryRepository as ImageRepositoryRepository;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
readonly class ImageProcessor implements ProcessorInterface
|
||||
{
|
||||
|
@ -28,6 +30,7 @@ readonly class ImageProcessor implements ProcessorInterface
|
|||
private ValidatorInterface $validator,
|
||||
private CreateImageAction $createImageActionController,
|
||||
private KernelInterface $kernel,
|
||||
private LoggerInterface $logger,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
@ -63,21 +66,36 @@ readonly class ImageProcessor implements ProcessorInterface
|
|||
$entity = $this->imageRepository->findOneByUuid($uriVariables['uuid']);
|
||||
}
|
||||
|
||||
try {
|
||||
$response = null;
|
||||
$image = null;
|
||||
if ($data->selectedImage) {
|
||||
$response = $this->createImageActionController->__invoke($data->queue, $data->selectedImage->getEntity(), $data->partition->getEntity(), $data->client->getEntity(), $data->gitRepository);
|
||||
} else {
|
||||
$image = $data->createOrUpdateEntity($entity);
|
||||
|
||||
if ($data->selectedImage){
|
||||
$response = $this->createImageActionController->__invoke($data->selectedImage->getEntity(), $data->partition->getEntity(), $data->client->getEntity());
|
||||
} else {
|
||||
$image = $data->createOrUpdateEntity($entity);
|
||||
if ($this->kernel->getEnvironment() !== 'test') {
|
||||
$response = $this->createImageActionController->__invoke($data->queue, $image, null, null, $data->gitRepository);
|
||||
}
|
||||
|
||||
if ($this->kernel->getEnvironment() !== 'test') {
|
||||
$response = $this->createImageActionController->__invoke($image);
|
||||
$this->validator->validate($image);
|
||||
$this->imageRepository->save($image);
|
||||
}
|
||||
|
||||
$this->validator->validate($image);
|
||||
$this->imageRepository->save($image);
|
||||
}
|
||||
if ($response instanceof JsonResponse && $response->getStatusCode() >= 400) {
|
||||
$content = json_decode($response->getContent(), true);
|
||||
throw new \Exception($content['error'] ?? 'Error creating image');
|
||||
}
|
||||
|
||||
return new ImageOutput($data->selectedImage?->getEntity() ?? $image);
|
||||
return new ImageOutput($data->selectedImage?->getEntity() ?? $image);
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error('Error processing image creation/update', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
throw new \Exception('Error processing image: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\State\Provider;
|
||||
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\Metadata\GetCollection;
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use ApiPlatform\Metadata\Patch;
|
||||
use ApiPlatform\Metadata\Put;
|
||||
use ApiPlatform\State\Pagination\TraversablePaginator;
|
||||
use ApiPlatform\State\ProviderInterface;
|
||||
use App\Dto\Input\GitImageRepositoryInput;
|
||||
use App\Dto\Output\GitImageRepositoryOutput;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
readonly class GitImageRepositoryProvider implements ProviderInterface
|
||||
{
|
||||
public function __construct(
|
||||
private ProviderInterface $collectionProvider,
|
||||
private ProviderInterface $itemProvider
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
|
||||
{
|
||||
switch ($operation){
|
||||
case $operation instanceof GetCollection:
|
||||
return $this->provideCollection($operation, $uriVariables, $context);
|
||||
case $operation instanceof Patch:
|
||||
case $operation instanceof Put:
|
||||
return $this->provideInput($operation, $uriVariables, $context);
|
||||
case $operation instanceof Get:
|
||||
return $this->provideItem($operation, $uriVariables, $context);
|
||||
}
|
||||
}
|
||||
|
||||
private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object
|
||||
{
|
||||
$paginator = $this->collectionProvider->provide($operation, $uriVariables, $context);
|
||||
|
||||
$items = new \ArrayObject();
|
||||
foreach ($paginator->getIterator() as $item){
|
||||
$items[] = new GitImageRepositoryOutput($item, $context);
|
||||
}
|
||||
|
||||
return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems());
|
||||
}
|
||||
|
||||
public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
|
||||
{
|
||||
$item = $this->itemProvider->provide($operation, $uriVariables, $context);
|
||||
|
||||
if (!$item) {
|
||||
throw new NotFoundHttpException('ImageImageRepository not found');
|
||||
}
|
||||
|
||||
return new GitImageRepositoryOutput($item);
|
||||
}
|
||||
|
||||
public function provideInput(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
|
||||
{
|
||||
if (isset($uriVariables['uuid'])) {
|
||||
$item = $this->itemProvider->provide($operation, $uriVariables, $context);
|
||||
|
||||
return $item !== null ? new GitImageRepositoryInput($item) : null;
|
||||
}
|
||||
|
||||
return new GitImageRepositoryInput();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
<?php
|
||||
|
||||
namespace App\State\Provider;
|
||||
|
||||
use ApiPlatform\Metadata\Get;
|
||||
use ApiPlatform\Metadata\GetCollection;
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use ApiPlatform\Metadata\Patch;
|
||||
use ApiPlatform\Metadata\Put;
|
||||
use ApiPlatform\State\Pagination\TraversablePaginator;
|
||||
use ApiPlatform\State\ProviderInterface;
|
||||
use App\Dto\Input\GitRepositoryInput;
|
||||
use App\Dto\Output\GitRepositoryOutput;
|
||||
use App\Service\ExternalGitRepositoryService;
|
||||
use App\Repository\ImageRepositoryRepository;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
readonly class GitRepositoryProvider implements ProviderInterface
|
||||
{
|
||||
public function __construct(
|
||||
private ExternalGitRepositoryService $externalService,
|
||||
private ImageRepositoryRepository $imageRepositoryRepository,
|
||||
private RequestStack $requestStack
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
|
||||
{
|
||||
switch ($operation){
|
||||
case $operation instanceof GetCollection:
|
||||
return $this->provideCollection($operation, $uriVariables, $context);
|
||||
case $operation instanceof Patch:
|
||||
case $operation instanceof Put:
|
||||
return $this->provideInput($operation, $uriVariables, $context);
|
||||
case $operation instanceof Get:
|
||||
return $this->provideItem($operation, $uriVariables, $context);
|
||||
}
|
||||
}
|
||||
|
||||
private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object
|
||||
{
|
||||
// Obtener el ImageRepository desde los parámetros de la request
|
||||
$request = $this->requestStack->getCurrentRequest();
|
||||
$repositoryId = $request->query->get('repository');
|
||||
|
||||
if (!$repositoryId) {
|
||||
throw new \InvalidArgumentException('El parámetro "repository" es requerido');
|
||||
}
|
||||
|
||||
$imageRepository = $this->imageRepositoryRepository->find($repositoryId);
|
||||
if (!$imageRepository) {
|
||||
throw new NotFoundHttpException('ImageRepository no encontrado');
|
||||
}
|
||||
|
||||
// Obtener repositorios de la API externa
|
||||
$externalRepositories = $this->externalService->getRepositories($imageRepository);
|
||||
|
||||
$items = new \ArrayObject();
|
||||
foreach ($externalRepositories as $externalData) {
|
||||
$gitRepository = $this->externalService->createEntityFromExternalData($externalData, $imageRepository);
|
||||
$items[] = new GitRepositoryOutput($gitRepository, $context);
|
||||
}
|
||||
|
||||
// Simular paginación básica
|
||||
$page = $request->query->getInt('page', 1);
|
||||
$limit = $request->query->getInt('limit', 10);
|
||||
$offset = ($page - 1) * $limit;
|
||||
|
||||
$paginatedItems = array_slice($items->getArrayCopy(), $offset, $limit);
|
||||
|
||||
return new TraversablePaginator(
|
||||
new \ArrayObject($paginatedItems),
|
||||
$page,
|
||||
$limit,
|
||||
count($items)
|
||||
);
|
||||
}
|
||||
|
||||
public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
|
||||
{
|
||||
// Obtener el nombre del repositorio desde los parámetros
|
||||
$request = $this->requestStack->getCurrentRequest();
|
||||
$repositoryId = $request->query->get('repository');
|
||||
$name = $uriVariables['name'] ?? $request->query->get('name');
|
||||
|
||||
if (!$repositoryId || !$name) {
|
||||
throw new \InvalidArgumentException('Los parámetros "repository" y "name" son requeridos');
|
||||
}
|
||||
|
||||
$imageRepository = $this->imageRepositoryRepository->find($repositoryId);
|
||||
if (!$imageRepository) {
|
||||
throw new NotFoundHttpException('ImageRepository no encontrado');
|
||||
}
|
||||
|
||||
// Obtener repositorio específico de la API externa
|
||||
$externalData = $this->externalService->getRepository($name, $imageRepository);
|
||||
|
||||
if (!$externalData) {
|
||||
throw new NotFoundHttpException('GitRepository no encontrado');
|
||||
}
|
||||
|
||||
$gitRepository = $this->externalService->createEntityFromExternalData($externalData, $imageRepository);
|
||||
return new GitRepositoryOutput($gitRepository);
|
||||
}
|
||||
|
||||
public function provideInput(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
|
||||
{
|
||||
if (isset($uriVariables['name'])) {
|
||||
// Para operaciones de actualización, necesitamos obtener el repositorio existente
|
||||
$request = $this->requestStack->getCurrentRequest();
|
||||
$repositoryId = $request->query->get('repository');
|
||||
$name = $uriVariables['name'];
|
||||
|
||||
if (!$repositoryId) {
|
||||
throw new \InvalidArgumentException('El parámetro "repository" es requerido');
|
||||
}
|
||||
|
||||
$imageRepository = $this->imageRepositoryRepository->find($repositoryId);
|
||||
if (!$imageRepository) {
|
||||
throw new NotFoundHttpException('ImageRepository no encontrado');
|
||||
}
|
||||
|
||||
$externalData = $this->externalService->getRepository($name, $imageRepository);
|
||||
if (!$externalData) {
|
||||
throw new NotFoundHttpException('GitRepository no encontrado');
|
||||
}
|
||||
|
||||
$gitRepository = $this->externalService->createEntityFromExternalData($externalData, $imageRepository);
|
||||
return new GitRepositoryInput($gitRepository);
|
||||
}
|
||||
|
||||
return new GitRepositoryInput();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue