From af5ad811990f6478dba0b96b2a2e81c545f97605 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Thu, 26 Jun 2025 17:01:16 +0200 Subject: [PATCH] refs #1975. Integration ogGit. Crete image and deploy --- config/api_platform/GitImageRepository.yaml | 50 ------- config/api_platform/GitRepository.yaml | 109 ++++++++++++++ config/api_platform/ImageRepository.yaml | 22 ++- config/services.yaml | 5 - config/services/api_platform.yaml | 26 +++- migrations/Version20250618114502.php | 37 +++++ migrations/Version20250618115400.php | 35 +++++ migrations/Version20250626145458.php | 37 +++++ src/Controller/DeployGitImageAction.php | 88 +++++++++++ .../OgAgent/DeployGitImageAction.php | 91 ++++++++++++ .../Git/CreateRepositoryAction.php | 8 +- .../OgRepository/Git/GetBranchesAction.php | 36 +++++ .../OgRepository/Git/GetCollectionAction.php | 4 + .../OgRepository/Git/GetCommitsAction.php | 36 +++++ ...gsAction.php => GetRepositoriesAction.php} | 14 +- .../{CreateTagAction.php => SshKeyAction.php} | 28 ++-- .../OgRepository/Git/SyncAction.php | 73 --------- src/Dto/Input/DeployGitImageInput.php | 49 ++++++ src/Dto/Input/GetBranchesInput.php | 26 ++++ src/Dto/Input/GetCommitsInput.php | 36 +++++ src/Dto/Input/GitImageRepositoryInput.php | 33 ----- src/Dto/Input/GitRepositoryInput.php | 71 +++++++++ src/Dto/Output/GitImageRepositoryOutput.php | 62 -------- src/Dto/Output/GitRepositoryOutput.php | 101 +++++++++++++ src/Entity/GitImageRepository.php | 134 ----------------- src/Entity/GitRepository.php | 51 +++++++ src/Entity/Image.php | 37 ----- src/Entity/ImageRepository.php | 37 ----- .../GitImageRepositoryRepository.php | 33 ----- src/Repository/GitRepositoryRepository.php | 19 +++ src/Service/ExternalGitRepositoryService.php | 139 ++++++++++++++++++ .../Processor/GitImageRepositoryProcessor.php | 68 --------- .../Processor/GitRepositoryProcessor.php | 113 ++++++++++++++ .../ImageImageRepositoryProcessor.php | 16 +- src/State/Processor/ImageProcessor.php | 38 +++-- .../Provider/GitImageRepositoryProvider.php | 71 --------- src/State/Provider/GitRepositoryProvider.php | 136 +++++++++++++++++ 37 files changed, 1317 insertions(+), 652 deletions(-) delete mode 100644 config/api_platform/GitImageRepository.yaml create mode 100644 config/api_platform/GitRepository.yaml create mode 100644 migrations/Version20250618114502.php create mode 100644 migrations/Version20250618115400.php create mode 100644 migrations/Version20250626145458.php create mode 100644 src/Controller/DeployGitImageAction.php create mode 100644 src/Controller/OgAgent/DeployGitImageAction.php create mode 100644 src/Controller/OgRepository/Git/GetBranchesAction.php create mode 100644 src/Controller/OgRepository/Git/GetCommitsAction.php rename src/Controller/OgRepository/Git/{GetTagsAction.php => GetRepositoriesAction.php} (72%) rename src/Controller/OgRepository/Git/{CreateTagAction.php => SshKeyAction.php} (52%) delete mode 100644 src/Controller/OgRepository/Git/SyncAction.php create mode 100644 src/Dto/Input/DeployGitImageInput.php create mode 100644 src/Dto/Input/GetBranchesInput.php create mode 100644 src/Dto/Input/GetCommitsInput.php delete mode 100644 src/Dto/Input/GitImageRepositoryInput.php create mode 100644 src/Dto/Input/GitRepositoryInput.php delete mode 100644 src/Dto/Output/GitImageRepositoryOutput.php create mode 100644 src/Dto/Output/GitRepositoryOutput.php delete mode 100644 src/Entity/GitImageRepository.php create mode 100644 src/Entity/GitRepository.php delete mode 100644 src/Repository/GitImageRepositoryRepository.php create mode 100644 src/Repository/GitRepositoryRepository.php create mode 100644 src/Service/ExternalGitRepositoryService.php delete mode 100644 src/State/Processor/GitImageRepositoryProcessor.php create mode 100644 src/State/Processor/GitRepositoryProcessor.php delete mode 100644 src/State/Provider/GitImageRepositoryProvider.php create mode 100644 src/State/Provider/GitRepositoryProvider.php diff --git a/config/api_platform/GitImageRepository.yaml b/config/api_platform/GitImageRepository.yaml deleted file mode 100644 index b1997a2..0000000 --- a/config/api_platform/GitImageRepository.yaml +++ /dev/null @@ -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 \ No newline at end of file diff --git a/config/api_platform/GitRepository.yaml b/config/api_platform/GitRepository.yaml new file mode 100644 index 0000000..f4b7cf4 --- /dev/null +++ b/config/api_platform/GitRepository.yaml @@ -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 \ No newline at end of file diff --git a/config/api_platform/ImageRepository.yaml b/config/api_platform/ImageRepository.yaml index 346aceb..20d5f1d 100644 --- a/config/api_platform/ImageRepository.yaml +++ b/config/api_platform/ImageRepository.yaml @@ -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: diff --git a/config/services.yaml b/config/services.yaml index 879364b..5ece707 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -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' diff --git a/config/services/api_platform.yaml b/config/services/api_platform.yaml index fd70e1d..087e0f9 100644 --- a/config/services/api_platform.yaml +++ b/config/services/api_platform.yaml @@ -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' ] + diff --git a/migrations/Version20250618114502.php b/migrations/Version20250618114502.php new file mode 100644 index 0000000..98780e3 --- /dev/null +++ b/migrations/Version20250618114502.php @@ -0,0 +1,37 @@ +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'); + } +} diff --git a/migrations/Version20250618115400.php b/migrations/Version20250618115400.php new file mode 100644 index 0000000..604f52a --- /dev/null +++ b/migrations/Version20250618115400.php @@ -0,0 +1,35 @@ +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'); + } +} diff --git a/migrations/Version20250626145458.php b/migrations/Version20250626145458.php new file mode 100644 index 0000000..ecacf64 --- /dev/null +++ b/migrations/Version20250626145458.php @@ -0,0 +1,37 @@ +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)'); + } +} diff --git a/src/Controller/DeployGitImageAction.php b/src/Controller/DeployGitImageAction.php new file mode 100644 index 0000000..62e1f16 --- /dev/null +++ b/src/Controller/DeployGitImageAction.php @@ -0,0 +1,88 @@ +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, + ]; + } +} \ No newline at end of file diff --git a/src/Controller/OgAgent/DeployGitImageAction.php b/src/Controller/OgAgent/DeployGitImageAction.php new file mode 100644 index 0000000..e9b522d --- /dev/null +++ b/src/Controller/OgAgent/DeployGitImageAction.php @@ -0,0 +1,91 @@ +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; + } +} \ No newline at end of file diff --git a/src/Controller/OgRepository/Git/CreateRepositoryAction.php b/src/Controller/OgRepository/Git/CreateRepositoryAction.php index f90aac8..b1e9d29 100644 --- a/src/Controller/OgRepository/Git/CreateRepositoryAction.php +++ b/src/Controller/OgRepository/Git/CreateRepositoryAction.php @@ -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'); diff --git a/src/Controller/OgRepository/Git/GetBranchesAction.php b/src/Controller/OgRepository/Git/GetBranchesAction.php new file mode 100644 index 0000000..7e8694b --- /dev/null +++ b/src/Controller/OgRepository/Git/GetBranchesAction.php @@ -0,0 +1,36 @@ +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); + } +} \ No newline at end of file diff --git a/src/Controller/OgRepository/Git/GetCollectionAction.php b/src/Controller/OgRepository/Git/GetCollectionAction.php index 55cc436..1703468 100644 --- a/src/Controller/OgRepository/Git/GetCollectionAction.php +++ b/src/Controller/OgRepository/Git/GetCollectionAction.php @@ -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); } } \ No newline at end of file diff --git a/src/Controller/OgRepository/Git/GetCommitsAction.php b/src/Controller/OgRepository/Git/GetCommitsAction.php new file mode 100644 index 0000000..0818300 --- /dev/null +++ b/src/Controller/OgRepository/Git/GetCommitsAction.php @@ -0,0 +1,36 @@ +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); + } +} \ No newline at end of file diff --git a/src/Controller/OgRepository/Git/GetTagsAction.php b/src/Controller/OgRepository/Git/GetRepositoriesAction.php similarity index 72% rename from src/Controller/OgRepository/Git/GetTagsAction.php rename to src/Controller/OgRepository/Git/GetRepositoriesAction.php index 55a94d3..ac39a75 100644 --- a/src/Controller/OgRepository/Git/GetTagsAction.php +++ b/src/Controller/OgRepository/Git/GetRepositoriesAction.php @@ -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); diff --git a/src/Controller/OgRepository/Git/CreateTagAction.php b/src/Controller/OgRepository/Git/SshKeyAction.php similarity index 52% rename from src/Controller/OgRepository/Git/CreateTagAction.php rename to src/Controller/OgRepository/Git/SshKeyAction.php index 43c491e..45752f8 100644 --- a/src/Controller/OgRepository/Git/CreateTagAction.php +++ b/src/Controller/OgRepository/Git/SshKeyAction.php @@ -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); } } \ No newline at end of file diff --git a/src/Controller/OgRepository/Git/SyncAction.php b/src/Controller/OgRepository/Git/SyncAction.php deleted file mode 100644 index 1168562..0000000 --- a/src/Controller/OgRepository/Git/SyncAction.php +++ /dev/null @@ -1,73 +0,0 @@ -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); - } -} \ No newline at end of file diff --git a/src/Dto/Input/DeployGitImageInput.php b/src/Dto/Input/DeployGitImageInput.php new file mode 100644 index 0000000..130190f --- /dev/null +++ b/src/Dto/Input/DeployGitImageInput.php @@ -0,0 +1,49 @@ +description = $gitImageRepository->getDescription(); - } - - public function createOrUpdateEntity(?GitImageRepository $gitImageRepository = null): GitImageRepository - { - if (!$gitImageRepository) { - $gitImageRepository = new GitImageRepository(); - } - - $gitImageRepository->setDescription($this->description); - - return $gitImageRepository; - } -} \ No newline at end of file diff --git a/src/Dto/Input/GitRepositoryInput.php b/src/Dto/Input/GitRepositoryInput.php new file mode 100644 index 0000000..77adc08 --- /dev/null +++ b/src/Dto/Input/GitRepositoryInput.php @@ -0,0 +1,71 @@ +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; + } +} \ No newline at end of file diff --git a/src/Dto/Output/GitImageRepositoryOutput.php b/src/Dto/Output/GitImageRepositoryOutput.php deleted file mode 100644 index aeceb17..0000000 --- a/src/Dto/Output/GitImageRepositoryOutput.php +++ /dev/null @@ -1,62 +0,0 @@ -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(); - } -} \ No newline at end of file diff --git a/src/Dto/Output/GitRepositoryOutput.php b/src/Dto/Output/GitRepositoryOutput.php new file mode 100644 index 0000000..9040e0f --- /dev/null +++ b/src/Dto/Output/GitRepositoryOutput.php @@ -0,0 +1,101 @@ +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(); + } +} \ No newline at end of file diff --git a/src/Entity/GitImageRepository.php b/src/Entity/GitImageRepository.php deleted file mode 100644 index 2a56010..0000000 --- a/src/Entity/GitImageRepository.php +++ /dev/null @@ -1,134 +0,0 @@ -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; - } -} diff --git a/src/Entity/GitRepository.php b/src/Entity/GitRepository.php new file mode 100644 index 0000000..de54128 --- /dev/null +++ b/src/Entity/GitRepository.php @@ -0,0 +1,51 @@ +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; + } +} diff --git a/src/Entity/Image.php b/src/Entity/Image.php index 5e465cd..24b061e 100644 --- a/src/Entity/Image.php +++ b/src/Entity/Image.php @@ -43,12 +43,6 @@ class Image extends AbstractEntity #[ORM\Column(nullable: true)] private ?int $version = null; - /** - * @var Collection - */ - #[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 - */ - 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; diff --git a/src/Entity/ImageRepository.php b/src/Entity/ImageRepository.php index 8be575a..7588190 100644 --- a/src/Entity/ImageRepository.php +++ b/src/Entity/ImageRepository.php @@ -32,17 +32,10 @@ class ImageRepository extends AbstractEntity #[ORM\Column(length: 255, nullable: true)] private ?string $sshPort = null; - /** - * @var Collection - */ - #[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 - */ - 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; - } } diff --git a/src/Repository/GitImageRepositoryRepository.php b/src/Repository/GitImageRepositoryRepository.php deleted file mode 100644 index d9104c7..0000000 --- a/src/Repository/GitImageRepositoryRepository.php +++ /dev/null @@ -1,33 +0,0 @@ - - */ -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(); - } -} diff --git a/src/Repository/GitRepositoryRepository.php b/src/Repository/GitRepositoryRepository.php new file mode 100644 index 0000000..5cccbb5 --- /dev/null +++ b/src/Repository/GitRepositoryRepository.php @@ -0,0 +1,19 @@ + + */ +class GitRepositoryRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, GitRepository::class); + } + +} diff --git a/src/Service/ExternalGitRepositoryService.php b/src/Service/ExternalGitRepositoryService.php new file mode 100644 index 0000000..20e0962 --- /dev/null +++ b/src/Service/ExternalGitRepositoryService.php @@ -0,0 +1,139 @@ +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; + } +} \ No newline at end of file diff --git a/src/State/Processor/GitImageRepositoryProcessor.php b/src/State/Processor/GitImageRepositoryProcessor.php deleted file mode 100644 index 095838e..0000000 --- a/src/State/Processor/GitImageRepositoryProcessor.php +++ /dev/null @@ -1,68 +0,0 @@ -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; - } -} diff --git a/src/State/Processor/GitRepositoryProcessor.php b/src/State/Processor/GitRepositoryProcessor.php new file mode 100644 index 0000000..f6bc16f --- /dev/null +++ b/src/State/Processor/GitRepositoryProcessor.php @@ -0,0 +1,113 @@ +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; + } +} \ No newline at end of file diff --git a/src/State/Processor/ImageImageRepositoryProcessor.php b/src/State/Processor/ImageImageRepositoryProcessor.php index d4fed62..c5e53a7 100644 --- a/src/State/Processor/ImageImageRepositoryProcessor.php +++ b/src/State/Processor/ImageImageRepositoryProcessor.php @@ -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; } diff --git a/src/State/Processor/ImageProcessor.php b/src/State/Processor/ImageProcessor.php index dbc5302..24c94e2 100644 --- a/src/State/Processor/ImageProcessor.php +++ b/src/State/Processor/ImageProcessor.php @@ -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 diff --git a/src/State/Provider/GitImageRepositoryProvider.php b/src/State/Provider/GitImageRepositoryProvider.php deleted file mode 100644 index a13103b..0000000 --- a/src/State/Provider/GitImageRepositoryProvider.php +++ /dev/null @@ -1,71 +0,0 @@ -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(); - } -} diff --git a/src/State/Provider/GitRepositoryProvider.php b/src/State/Provider/GitRepositoryProvider.php new file mode 100644 index 0000000..3f95cbb --- /dev/null +++ b/src/State/Provider/GitRepositoryProvider.php @@ -0,0 +1,136 @@ +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(); + } +} \ No newline at end of file