From 43f81a833eac1ccd1f02200cd4612ab1a9062c18 Mon Sep 17 00:00:00 2001 From: Manuel Aranda Date: Thu, 8 May 2025 17:02:27 +0200 Subject: [PATCH] refs #1975. Integration ogGit. Create table and init API --- config/api_platform/GitImageRepository.yaml | 41 +++++++++ config/api_platform/ImageRepository.yaml | 21 ++++- migrations/Version20250430135412.php | 33 +++++++ migrations/Version20250430140218.php | 35 ++++++++ migrations/Version20250430140326.php | 31 +++++++ migrations/Version20250508134732.php | 33 +++++++ .../OgRepository/Git/GetCollectionAction.php | 31 +++++++ .../OgRepository/Git/SyncAction.php | 73 +++++++++++++++ .../Image/ConvertImageToVirtualAction.php | 4 + .../{ => Image}/GetCollectionAction.php | 4 +- .../OgRepository/{ => Image}/SyncAction.php | 3 +- .../Webhook/ResponseController.php | 5 +- src/Dto/Input/GitImageRepositoryInput.php | 33 +++++++ src/Dto/Output/GitImageRepositoryOutput.php | 54 +++++++++++ src/Entity/GitImageRepository.php | 89 +++++++++++++++++++ src/Entity/ImageRepository.php | 37 ++++++++ .../GitImageRepositoryRepository.php | 18 ++++ .../Processor/GitImageRepositoryProcessor.php | 68 ++++++++++++++ .../Provider/GitImageRepositoryProvider.php | 71 +++++++++++++++ 19 files changed, 678 insertions(+), 6 deletions(-) create mode 100644 config/api_platform/GitImageRepository.yaml create mode 100644 migrations/Version20250430135412.php create mode 100644 migrations/Version20250430140218.php create mode 100644 migrations/Version20250430140326.php create mode 100644 migrations/Version20250508134732.php create mode 100644 src/Controller/OgRepository/Git/GetCollectionAction.php create mode 100644 src/Controller/OgRepository/Git/SyncAction.php rename src/Controller/OgRepository/{ => Image}/GetCollectionAction.php (90%) rename src/Controller/OgRepository/{ => Image}/SyncAction.php (96%) create mode 100644 src/Dto/Input/GitImageRepositoryInput.php create mode 100644 src/Dto/Output/GitImageRepositoryOutput.php create mode 100644 src/Entity/GitImageRepository.php create mode 100644 src/Repository/GitImageRepositoryRepository.php create mode 100644 src/State/Processor/GitImageRepositoryProcessor.php create mode 100644 src/State/Provider/GitImageRepositoryProvider.php diff --git a/config/api_platform/GitImageRepository.yaml b/config/api_platform/GitImageRepository.yaml new file mode 100644 index 0000000..9261f82 --- /dev/null +++ b/config/api_platform/GitImageRepository.yaml @@ -0,0 +1,41 @@ +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 + + +properties: + App\Entity\GitImageRepository: + id: + identifier: false + uuid: + identifier: true \ No newline at end of file diff --git a/config/api_platform/ImageRepository.yaml b/config/api_platform/ImageRepository.yaml index 97cd0b9..346aceb 100644 --- a/config/api_platform/ImageRepository.yaml +++ b/config/api_platform/ImageRepository.yaml @@ -30,7 +30,7 @@ resources: method: POST input: false uriTemplate: /image-repositories/server/{uuid}/sync - controller: App\Controller\OgRepository\SyncAction + controller: App\Controller\OgRepository\Image\SyncAction wol_client: class: ApiPlatform\Metadata\Post @@ -46,7 +46,7 @@ resources: method: POST input: false uriTemplate: /image-repositories/server/{uuid}/get-collection - controller: App\Controller\OgRepository\GetCollectionAction + controller: App\Controller\OgRepository\Image\GetCollectionAction images_ogrepository_status: shortName: OgRepository Server @@ -75,6 +75,23 @@ resources: uriTemplate: /image-repositories/{uuid}/convert-image controller: App\Controller\OgRepository\Image\ConvertAction + get_collection_images_oggit: + shortName: OgRepository Server + description: Get collection of image in OgRepository + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /image-repositories/server/git/{uuid}/get-collection + controller: App\Controller\OgRepository\Git\GetCollectionAction + + git_image_ogrepository_sync: + shortName: OgRepository Server + class: ApiPlatform\Metadata\Post + method: POST + input: false + uriTemplate: /image-repositories/server/git/{uuid}/sync + controller: App\Controller\OgRepository\Git\SyncAction + properties: App\Entity\ImageRepository: id: diff --git a/migrations/Version20250430135412.php b/migrations/Version20250430135412.php new file mode 100644 index 0000000..23612d9 --- /dev/null +++ b/migrations/Version20250430135412.php @@ -0,0 +1,33 @@ +addSql('CREATE TABLE git_image_repository (id INT AUTO_INCREMENT NOT NULL, image_id INT 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, status VARCHAR(255) NOT NULL, branch VARCHAR(255) NOT NULL, created TINYINT(1) NOT NULL, UNIQUE INDEX UNIQ_E6944D5ED17F50A6 (uuid), INDEX IDX_E6944D5E3DA5256D (image_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('ALTER TABLE git_image_repository ADD CONSTRAINT FK_E6944D5E3DA5256D FOREIGN KEY (image_id) REFERENCES image (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_E6944D5E3DA5256D'); + $this->addSql('DROP TABLE git_image_repository'); + } +} diff --git a/migrations/Version20250430140218.php b/migrations/Version20250430140218.php new file mode 100644 index 0000000..a8129e4 --- /dev/null +++ b/migrations/Version20250430140218.php @@ -0,0 +1,35 @@ +addSql('ALTER TABLE git_image_repository ADD image_repository_id INT DEFAULT NULL'); + $this->addSql('ALTER TABLE git_image_repository ADD CONSTRAINT FK_E6944D5E14C736FC FOREIGN KEY (image_repository_id) REFERENCES image_repository (id)'); + $this->addSql('CREATE INDEX IDX_E6944D5E14C736FC ON git_image_repository (image_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_E6944D5E14C736FC'); + $this->addSql('DROP INDEX IDX_E6944D5E14C736FC ON git_image_repository'); + $this->addSql('ALTER TABLE git_image_repository DROP image_repository_id'); + } +} diff --git a/migrations/Version20250430140326.php b/migrations/Version20250430140326.php new file mode 100644 index 0000000..30d1c61 --- /dev/null +++ b/migrations/Version20250430140326.php @@ -0,0 +1,31 @@ +addSql('ALTER TABLE git_image_repository ADD name VARCHAR(255) NOT NULL'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE git_image_repository DROP name'); + } +} diff --git a/migrations/Version20250508134732.php b/migrations/Version20250508134732.php new file mode 100644 index 0000000..c337ed2 --- /dev/null +++ b/migrations/Version20250508134732.php @@ -0,0 +1,33 @@ +addSql('ALTER TABLE `partition` DROP FOREIGN KEY FK_9EB910E43DA5256D'); + $this->addSql('ALTER TABLE `partition` ADD CONSTRAINT FK_9EB910E43DA5256D FOREIGN KEY (image_id) REFERENCES image_image_repository (id)'); + } + + public function down(Schema $schema): void + { + // this down() migration is auto-generated, please modify it to your needs + $this->addSql('ALTER TABLE `partition` DROP FOREIGN KEY FK_9EB910E43DA5256D'); + $this->addSql('ALTER TABLE `partition` ADD CONSTRAINT FK_9EB910E43DA5256D FOREIGN KEY (image_id) REFERENCES image (id)'); + } +} diff --git a/src/Controller/OgRepository/Git/GetCollectionAction.php b/src/Controller/OgRepository/Git/GetCollectionAction.php new file mode 100644 index 0000000..55cc436 --- /dev/null +++ b/src/Controller/OgRepository/Git/GetCollectionAction.php @@ -0,0 +1,31 @@ +createRequest('GET', 'http://'.$data->getIp().':8006/ogrepository/v1/git/repositories'); + + 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 new file mode 100644 index 0000000..1168562 --- /dev/null +++ b/src/Controller/OgRepository/Git/SyncAction.php @@ -0,0 +1,73 @@ +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/Controller/OgRepository/Image/ConvertImageToVirtualAction.php b/src/Controller/OgRepository/Image/ConvertImageToVirtualAction.php index cf3545c..7591e08 100644 --- a/src/Controller/OgRepository/Image/ConvertImageToVirtualAction.php +++ b/src/Controller/OgRepository/Image/ConvertImageToVirtualAction.php @@ -48,6 +48,10 @@ class ConvertImageToVirtualAction extends AbstractOgRepositoryController $content = $this->createRequest('PUT', 'http://'.$repository->getIp().':8006/ogrepository/v1/images/virtual', $params); + if (isset($content['error']) && $content['code'] === Response::HTTP_INTERNAL_SERVER_ERROR ) { + throw new ValidatorException('Error converting image'); + } + $inputData = [ 'imageName' => $image->getName(), 'repositoryUuid' => $repository->getUuid(), diff --git a/src/Controller/OgRepository/GetCollectionAction.php b/src/Controller/OgRepository/Image/GetCollectionAction.php similarity index 90% rename from src/Controller/OgRepository/GetCollectionAction.php rename to src/Controller/OgRepository/Image/GetCollectionAction.php index 594385a..26a01c7 100644 --- a/src/Controller/OgRepository/GetCollectionAction.php +++ b/src/Controller/OgRepository/Image/GetCollectionAction.php @@ -1,7 +1,8 @@ jsonResponseError('Action failed', Response::HTTP_BAD_REQUEST, $trace); } + $latestImageRepo = $this->entityManager->getRepository(ImageImageRepository::class)->findLatestVersionByImageAndRepository($image, $repository); + $newImageRepo = new ImageImageRepository(); - $newImageRepo->setName($image->getName().'_v'.($originImageImageRepository->getVersion() + 1)); + $newImageRepo->setName($image->getName().'_v'.($latestImageRepo ? $latestImageRepo->getVersion() + 1 : 1)); $newImageRepo->setImage($image); + $newImageRepo->setVersion($latestImageRepo ? $latestImageRepo->getVersion() + 1 : 1); $newImageRepo->setRepository($repository); $newImageRepo->setStatus(ImageStatus::SUCCESS); diff --git a/src/Dto/Input/GitImageRepositoryInput.php b/src/Dto/Input/GitImageRepositoryInput.php new file mode 100644 index 0000000..d391f90 --- /dev/null +++ b/src/Dto/Input/GitImageRepositoryInput.php @@ -0,0 +1,33 @@ +name = $gitImageRepository->getName(); + } + + public function createOrUpdateEntity(?GitImageRepository $gitImageRepository = null): GitImageRepository + { + if (!$gitImageRepository) { + $gitImageRepository = new GitImageRepository(); + } + + $gitImageRepository->setName($this->name); + + return $gitImageRepository; + } +} \ No newline at end of file diff --git a/src/Dto/Output/GitImageRepositoryOutput.php b/src/Dto/Output/GitImageRepositoryOutput.php new file mode 100644 index 0000000..ee01d09 --- /dev/null +++ b/src/Dto/Output/GitImageRepositoryOutput.php @@ -0,0 +1,54 @@ +getImage()) { + $this->image = new ImageOutput($gitImageRepository->getImage()); + } + } + + if ($gitImageRepository->getImageRepository()) { + $this->imageRepository = new ImageRepositoryOutput($gitImageRepository->getImageRepository()); + } + + $this->name = $gitImageRepository->getName(); + $this->status = $gitImageRepository->getStatus(); + $this->branch = $gitImageRepository->getBranch(); + $this->createdAt = $gitImageRepository->getCreatedAt(); + $this->createdBy = $gitImageRepository->getCreatedBy(); + } +} \ No newline at end of file diff --git a/src/Entity/GitImageRepository.php b/src/Entity/GitImageRepository.php new file mode 100644 index 0000000..3a60cc2 --- /dev/null +++ b/src/Entity/GitImageRepository.php @@ -0,0 +1,89 @@ +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 getBranch(): ?string + { + return $this->branch; + } + + public function setBranch(string $branch): static + { + $this->branch = $branch; + + return $this; + } + + public function isCreated(): ?bool + { + return $this->created; + } + + public function setCreated(bool $created): static + { + $this->created = $created; + + return $this; + } + + public function getImageRepository(): ?ImageRepository + { + return $this->imageRepository; + } + + public function setImageRepository(?ImageRepository $imageRepository): static + { + $this->imageRepository = $imageRepository; + + return $this; + } +} diff --git a/src/Entity/ImageRepository.php b/src/Entity/ImageRepository.php index 7588190..77dd9d8 100644 --- a/src/Entity/ImageRepository.php +++ b/src/Entity/ImageRepository.php @@ -32,10 +32,17 @@ class ImageRepository extends AbstractEntity #[ORM\Column(length: 255, nullable: true)] private ?string $sshPort = null; + /** + * @var Collection + */ + #[ORM\OneToMany(mappedBy: 'imageRepository', targetEntity: GitImageRepository::class)] + private Collection $gitImageRepositories; + public function __construct() { parent::__construct(); $this->imageImageRepositories = new ArrayCollection(); + $this->gitImageRepositories = new ArrayCollection(); } public function getIp(): ?string @@ -115,4 +122,34 @@ 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 new file mode 100644 index 0000000..a9b5369 --- /dev/null +++ b/src/Repository/GitImageRepositoryRepository.php @@ -0,0 +1,18 @@ + + */ +class GitImageRepositoryRepository extends AbstractRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, GitImageRepository::class); + } +} diff --git a/src/State/Processor/GitImageRepositoryProcessor.php b/src/State/Processor/GitImageRepositoryProcessor.php new file mode 100644 index 0000000..095838e --- /dev/null +++ b/src/State/Processor/GitImageRepositoryProcessor.php @@ -0,0 +1,68 @@ +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/Provider/GitImageRepositoryProvider.php b/src/State/Provider/GitImageRepositoryProvider.php new file mode 100644 index 0000000..a13103b --- /dev/null +++ b/src/State/Provider/GitImageRepositoryProvider.php @@ -0,0 +1,71 @@ +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(); + } +}