refs #601. Integration API pxe-boot-file

feature/comunication-ogagent
Manuel Aranda Rosales 2024-08-13 11:52:04 +02:00
parent aa2059b70c
commit 3f5004dddd
9 changed files with 353 additions and 26 deletions

View File

@ -0,0 +1,31 @@
resources:
App\Entity\PxeBootFile:
processor: App\State\Processor\PxeBootFileProcessor
input: App\Dto\Input\PxeBootFileInput
output: App\Dto\Output\PxeBootFileOutput
normalizationContext:
groups: ['default', 'pxe-boot-file:read']
denormalizationContext:
groups: ['pxe-boot-file:write']
operations:
ApiPlatform\Metadata\GetCollection:
provider: App\State\Provider\PPxeBootFileProvider
filters:
- 'api_platform.filter.pxe_boot_file.order'
- 'api_platform.filter.pxe_boot_file.search'
ApiPlatform\Metadata\Get:
provider: App\State\Provider\PxeTemplateProvider
ApiPlatform\Metadata\Put:
provider: App\State\Provider\PxeTemplateProvider
ApiPlatform\Metadata\Patch:
provider: App\State\Provider\PxeTemplateProvider
ApiPlatform\Metadata\Post: ~
ApiPlatform\Metadata\Delete: ~
properties:
App\Entity\PxeBootFile:
id:
identifier: false
uuid:
identifier: true

View File

@ -114,3 +114,7 @@ services:
$collectionProvider: '@api_platform.doctrine.orm.state.collection_provider'
$itemProvider: '@api_platform.doctrine.orm.state.item_provider'
App\State\Provider\PxeBootFileProvider:
bind:
$collectionProvider: '@api_platform.doctrine.orm.state.collection_provider'
$itemProvider: '@api_platform.doctrine.orm.state.item_provider'

View File

@ -0,0 +1,55 @@
<?php
namespace App\Dto\Input;
use ApiPlatform\Metadata\ApiProperty;
use App\Dto\Output\ClientOutput;
use App\Dto\Output\PxeTemplateOutput;
use App\Entity\PxeBootFile;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
final class PxeBootFileInput
{
#[Assert\NotNull(message: 'validators.pxe_boot_file.template.not_null')]
#[Groups(['pxe-boot-file:write'])]
#[ApiProperty(description: 'The pxeTemplate of the pxeBootFile', example: "PxeTemplate 1")]
public ?PxeTemplateOutput $template = null;
/**
* @var ClientOutput[]
*/
#[Groups(['pxe-boot-file:write'])]
#[ApiProperty(description: 'The clients of the pxeBootFile', readableLink: false, writableLink: false, example: "Client 1")]
public array $clients = [];
public function __construct(?PxeBootFile $bootFile = null)
{
if (!$bootFile) {
return;
}
$this->template = $bootFile->getTemplate();
if ($bootFile->getClients()) {
foreach ($bootFile->getClients() as $client) {
$this->clients[] = new ClientOutput($client);
}
}
}
public function createOrUpdateEntity(?PxeBootFile $bootFile = null): PxeBootFile
{
if (!$bootFile) {
$bootFile = new PxeBootFile();
}
$bootFile->setTemplate($this->template);
foreach ($this->clients as $client) {
$clientsToAdd[] = $client->getEntity();
}
$bootFile->setClients( $clientsToAdd ?? [] );
return $bootFile;
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace App\Dto\Output;
use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\Get;
use App\Entity\Client;
use App\Entity\PxeBootFile;
use Symfony\Component\Serializer\Annotation\Groups;
#[Get(shortName: 'PxeBootFile')]
final class PxeBootFileOutput extends AbstractOutput
{
#[Groups(['pxe-boot-file:read'])]
public PxeTemplateOutput $template;
#[Groups(['pxe-boot-file:read'])]
public array $clients;
#[Groups(['pxe-boot-file:read'])]
public \DateTime $createdAt;
#[Groups(['pxe-boot-file:read'])]
public ?string $createdBy = null;
public function __construct(PxeBootFile $bootFile)
{
parent::__construct($bootFile);
$this->template = new PxeTemplateOutput($bootFile->getTemplate());
$this->clients = $bootFile->getClients()->map(
fn(Client $client) => new ClientOutput($client)
)->toArray();
$this->createdAt = $bootFile->getCreatedAt();
$this->createdBy = $bootFile->getCreatedBy();
}
}

View File

@ -66,4 +66,15 @@ class PxeBootFile extends AbstractEntity
return $this;
}
public function setClients(array $clients): static
{
$this->clients->clear();
foreach ($clients as $client){
$this->addClient($client);
}
return $this;
}
}

View File

@ -9,35 +9,10 @@ use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<PxeBootFile>
*/
class PxeBootFileRepository extends ServiceEntityRepository
class PxeBootFileRepository extends AbstractRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, PxeBootFile::class);
}
// /**
// * @return PxeBootFile[] Returns an array of PxeBootFile objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('p')
// ->andWhere('p.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('p.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?PxeBootFile
// {
// return $this->createQueryBuilder('p')
// ->andWhere('p.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}

View File

@ -0,0 +1,70 @@
<?php
namespace App\Service\OgBoot\PxeBootFile;
use App\Entity\PxeBootFile;
use Symfony\Component\HttpClient\HttpClient;
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;
use Symfony\Contracts\HttpClient\HttpClientInterface;
readonly class PostService
{
public function __construct(
private string $ogBootApiUrl
)
{
}
/**
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
* @throws RedirectionExceptionInterface
* @throws ClientExceptionInterface
*/
public function __invoke(PxeBootFile $bootFile)
{
$httpClient = HttpClient::create([
'verify_peer' => false, // Ignorar la verificación del certificado SSL
'verify_host' => false, // Ignorar la verificación del nombre del host
]);
foreach ($bootFile->getClients() as $client) {
$data = [
'template_name' => $bootFile->getTemplate()->getName(),
'mac' => $client->getMac(),
'ip' => $client->getIp(),
'server_ip' => '',
'router' => $client->getOrganizationalUnit()->getNetworkSettings()->getRouter(),
'netmask' => $client->getOrganizationalUnit()->getNetworkSettings()->getNetmask(),
'computer_name' => $client->getName(),
'netiface' => $client->getNetiface(),
'group' => $client->getOrganizationalUnit()->getName(),
'ogrepo' => $client->getRepository() ? $client->getRepository()->getIpAddress() : $client->getOrganizationalUnit()->getNetworkSettings()->getRepository()->getIpAddress(),
'oglive' => '',
'ogdns' => $client->getOrganizationalUnit()->getNetworkSettings()->getDns(),
'ogProxy' => $client->getOrganizationalUnit()->getNetworkSettings()->getProxy(),
'ogunit' => ''
];
try {
$response = $httpClient->request('POST', $this->ogBootApiUrl.'/ogboot/v1/pxes', [
'headers' => [
'accept' => 'application/json',
],
'json' => $data
]);
} catch (TransportExceptionInterface $e) {
return new JsonResponse( data: 'An error occurred', status: Response::HTTP_INTERNAL_SERVER_ERROR);
}
return json_decode($response->getContent(), true);
}
return 1;
}
}

View File

@ -0,0 +1,72 @@
<?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\PxeBootFileInput;
use App\Dto\Output\PxeBootFileOutput;
use App\Repository\PxeBootFileRepository;
use App\Service\OgBoot\PxeBootFile\PostService;
readonly class PxeBootFileProcessor implements ProcessorInterface
{
public function __construct(
private PxeBootFileRepository $bootFileRepository,
private ValidatorInterface $validator,
private PostService $postService
)
{
}
/**
* @throws \Exception
*/
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): PxeBootFileOutput|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 = []): PxeBootFileOutput
{
if (!($data instanceof PxeBootFileInput)) {
throw new \Exception(sprintf('data is not instance of %s', PxeBootFileInput::class));
}
$entity = null;
if (isset($uriVariables['uuid'])) {
$entity = $this->bootFileRepository->findOneByUuid($uriVariables['uuid']);
}
$pxeTemplate = $data->createOrUpdateEntity($entity);
$this->validator->validate($pxeTemplate);
$this->bootFileRepository->save($pxeTemplate);
$this->postService->__invoke($pxeTemplate);
return new PxeBootFileOutput($pxeTemplate);
}
private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null
{
$bootFile = $this->bootFileRepository->findOneByUuid($uriVariables['uuid']);
$this->bootFileRepository->delete($bootFile);
return null;
}
}

View File

@ -0,0 +1,71 @@
<?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\PxeBootFileInput;
use App\Dto\Output\PxeBootFileOutput;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
readonly class PxeBootFileProvider 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 PxeBootFileOutput($item);
}
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('PxeBootFile not found');
}
return new PxeBootFileOutput($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 PxeBootFileInput($item) : null;
}
return new PxeBootFileInput();
}
}