refs #423. Added ddbb and endpoint OperativeSystem

pull/7/head
Manuel Aranda Rosales 2024-06-18 10:40:35 +02:00
parent f64fbecd2e
commit 00b37723f6
19 changed files with 615 additions and 22 deletions

View File

@ -0,0 +1,31 @@
resources:
App\Entity\OperativeSystem:
processor: App\State\Processor\OperativeSystemProcessor
input: App\Dto\Input\OperativeSystemInput
output: App\Dto\Output\OperativeSystemOutput
normalization_context:
groups: ['default', 'operative-system:read']
denormalization_context:
groups: ['operative-system:write']
operations:
ApiPlatform\Metadata\GetCollection:
provider: App\State\Provider\OperativeSystemProvider
filters:
- 'api_platform.filter.operative-system.order'
- 'api_platform.filter.operative-system.search'
ApiPlatform\Metadata\Get:
provider: App\State\Provider\OperativeSystemProvider
ApiPlatform\Metadata\Put:
provider: App\State\Provider\OperativeSystemProvider
ApiPlatform\Metadata\Patch:
provider: App\State\Provider\OperativeSystemProvider
ApiPlatform\Metadata\Post: ~
ApiPlatform\Metadata\Delete: ~
properties:
App\Entity\OperativeSystem:
id:
identifier: false
uuid:
identifier: true

View File

@ -66,6 +66,11 @@ services:
$itemProvider: '@api_platform.doctrine.orm.state.item_provider'
App\State\Provider\NetworkSettingsProvider:
bind:
$collectionProvider: '@api_platform.doctrine.orm.state.collection_provider'
$itemProvider: '@api_platform.doctrine.orm.state.item_provider'
App\State\Provider\OperativeSystemProvider:
bind:
$collectionProvider: '@api_platform.doctrine.orm.state.collection_provider'
$itemProvider: '@api_platform.doctrine.orm.state.item_provider'

View File

@ -0,0 +1,41 @@
<?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 Version20240618083013 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 hardware_type (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, name VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_2AA5A113D17F50A6 (uuid), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('CREATE TABLE operative_system (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, name VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_E9C44095D17F50A6 (uuid), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('CREATE TABLE operative_system_type (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, name VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_4A13A156D17F50A6 (uuid), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
$this->addSql('ALTER TABLE hardware ADD type_id INT DEFAULT NULL, DROP type');
$this->addSql('ALTER TABLE hardware ADD CONSTRAINT FK_FE99E9E0C54C8C93 FOREIGN KEY (type_id) REFERENCES hardware_type (id)');
$this->addSql('CREATE INDEX IDX_FE99E9E0C54C8C93 ON hardware (type_id)');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE hardware DROP FOREIGN KEY FK_FE99E9E0C54C8C93');
$this->addSql('DROP TABLE hardware_type');
$this->addSql('DROP TABLE operative_system');
$this->addSql('DROP TABLE operative_system_type');
$this->addSql('DROP INDEX IDX_FE99E9E0C54C8C93 ON hardware');
$this->addSql('ALTER TABLE hardware ADD type VARCHAR(255) DEFAULT NULL, DROP type_id');
}
}

View File

@ -0,0 +1,35 @@
<?php
namespace App\Dto\Input;
use App\Entity\OperativeSystem;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
class OperativeSystemInput
{
#[Assert\NotBlank]
#[Groups(['operative-system:read'])]
public ?string $name = null;
public function __construct(?OperativeSystem $operativeSystem = null)
{
if (!$operativeSystem) {
return;
}
$this->name = $operativeSystem->getName();
}
public function createOrUpdateEntity(?OperativeSystem $operativeSystem = null): OperativeSystem
{
if (!$operativeSystem) {
$operativeSystem = new OperativeSystem();
}
$operativeSystem->setName($this->name);
return $operativeSystem;
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Dto\Output;
use ApiPlatform\Metadata\Get;
use App\Entity\OperativeSystem;
use Symfony\Component\Serializer\Annotation\Groups;
#[Get(shortName: 'OperativeSystem')]
final class OperativeSystemOutput extends AbstractOutput
{
#[Groups(['operative-system:read'])]
public string $name;
public function __construct(OperativeSystem $operativeSystem)
{
parent::__construct($operativeSystem);
$this->name = $operativeSystem->getName();
}
}

View File

@ -46,5 +46,4 @@ class PartitionOutput extends AbstractOutput
$this->osName = $partition->getOsName();
$this->memoryUsage = $partition->getMemoryUsage() / 100;
}
}

View File

@ -15,15 +15,15 @@ class Hardware extends AbstractEntity
#[ORM\Column(length: 255, nullable: true)]
private ?string $description = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $type = null;
/**
* @var Collection<int, HardwareProfile>
*/
#[ORM\ManyToMany(targetEntity: HardwareProfile::class, mappedBy: 'hardwareCollection')]
private Collection $hardwareProfiles;
#[ORM\ManyToOne]
private ?HardwareType $type = null;
public function __construct()
{
parent::__Construct();
@ -48,18 +48,6 @@ class Hardware extends AbstractEntity
return $this;
}
public function getType(): ?string
{
return $this->type;
}
public function setType(?string $type): static
{
$this->type = $type;
return $this;
}
/**
* @return Collection<int, HardwareProfile>
*/
@ -86,4 +74,16 @@ class Hardware extends AbstractEntity
return $this;
}
public function getType(): ?HardwareType
{
return $this->type;
}
public function setType(?HardwareType $type): static
{
$this->type = $type;
return $this;
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Entity;
use App\Repository\HardwareTypeRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: HardwareTypeRepository::class)]
class HardwareType extends AbstractEntity
{
use NameableTrait;
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Entity;
use App\Repository\OperativeSystemRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: OperativeSystemRepository::class)]
class OperativeSystem extends AbstractEntity
{
use NameableTrait;
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Entity;
use App\Repository\OperativeSystemTypeRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: OperativeSystemTypeRepository::class)]
class OperativeSystemType extends AbstractEntity
{
use NameableTrait;
}

View File

@ -0,0 +1,58 @@
<?php
namespace App\Factory;
use App\Entity\OperativeSystem;
use App\Repository\OperativeSystemRepository;
use Zenstruck\Foundry\ModelFactory;
use Zenstruck\Foundry\Persistence\PersistentProxyObjectFactory;
use Zenstruck\Foundry\Persistence\Proxy;
use Zenstruck\Foundry\Persistence\ProxyRepositoryDecorator;
/**
* @extends PersistentProxyObjectFactory<OperativeSystem>
*/
final class OperativeSystemFactory extends ModelFactory
{
/**
* @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services
*/
public function __construct()
{
parent::__construct();
}
public static function class(): string
{
return OperativeSystem::class;
}
/**
* @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories
*
* @todo add your default values here
*/
protected function getDefaults(): array
{
return [
'createdAt' => self::faker()->dateTime(),
'name' => self::faker()->text(255),
'updatedAt' => self::faker()->dateTime(),
];
}
/**
* @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization
*/
protected function initialize(): self
{
return $this
// ->afterInstantiate(function(OperativeSystem $operativeSystem): void {})
;
}
protected static function getClass(): string
{
return OperativeSystem::class;
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace App\Repository;
use App\Entity\HardwareType;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<HardwareType>
*/
class HardwareTypeRepository extends AbstractRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, HardwareType::class);
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace App\Repository;
use App\Entity\OperativeSystem;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<OperativeSystem>
*/
class OperativeSystemRepository extends AbstractRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, OperativeSystem::class);
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace App\Repository;
use App\Entity\OperativeSystemType;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<OperativeSystemType>
*/
class OperativeSystemTypeRepository extends AbstractRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, OperativeSystemType::class);
}
}

View File

@ -0,0 +1,74 @@
<?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\MenuInput;
use App\Dto\Input\OperativeSystemInput;
use App\Dto\Input\UserGroupInput;
use App\Dto\Output\MenuOutput;
use App\Dto\Output\OperativeSystemOutput;
use App\Dto\Output\UserGroupOutput;
use App\Repository\MenuRepository;
use App\Repository\OperativeSystemRepository;
use App\Repository\UserGroupRepository;
readonly class OperativeSystemProcessor implements ProcessorInterface
{
public function __construct(
private OperativeSystemRepository $operativeSystemRepository,
private ValidatorInterface $validator
)
{
}
/**
* @throws \Exception
*/
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): OperativeSystemOutput|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 = []): OperativeSystemOutput
{
if (!($data instanceof OperativeSystemInput)) {
throw new \Exception(sprintf('data is not instance of %s', MenuInput::class));
}
$entity = null;
if (isset($uriVariables['uuid'])) {
$entity = $this->operativeSystemRepository->findOneByUuid($uriVariables['uuid']);
}
$operativeSystem = $data->createOrUpdateEntity($entity);
$this->validator->validate($operativeSystem);
$this->operativeSystemRepository->save($operativeSystem);
return new OperativeSystemOutput($operativeSystem);
}
private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null
{
$user = $this->operativeSystemRepository->findOneByUuid($uriVariables['uuid']);
$this->operativeSystemRepository->delete($user);
return null;
}
}

View File

@ -0,0 +1,76 @@
<?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\ClientInput;
use App\Dto\Input\HardwareInput;
use App\Dto\Input\OperativeSystemInput;
use App\Dto\Output\ClientOutput;
use App\Dto\Output\HardwareOutput;
use App\Dto\Output\NetworkSettingsOutput;
use App\Dto\Output\OperativeSystemOutput;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class OperativeSystemProvider implements ProviderInterface
{
public function __construct(
private readonly ProviderInterface $collectionProvider,
private readonly 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 OperativeSystemOutput($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('Operative system not found');
}
return new OperativeSystemOutput($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 OperativeSystemInput($item) : null;
}
return new OperativeSystemInput();
}
}

View File

@ -140,6 +140,4 @@ class ClientTest extends AbstractTest
static::getContainer()->get('doctrine')->getRepository(Client::class)->findOneBy(['name' => self::CLIENT_DELETE])
);
}
}

View File

@ -0,0 +1,117 @@
<?php
namespace Functional;
use App\Entity\OperativeSystem;
use App\Factory\OperativeSystemFactory;
use App\Factory\OrganizationalUnitFactory;
use App\Factory\UserFactory;
use App\Model\UserGroupPermissions;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
class OperativeSystemTest extends AbstractTest
{
CONST string USER_ADMIN = 'ogadmin';
CONST string OS_CREATE = 'test-os-create';
CONST string OS_UPDATE = 'test-os-update';
CONST string OS_DELETE = 'test-os-delete';
/**
* @throws RedirectionExceptionInterface
* @throws DecodingExceptionInterface
* @throws ClientExceptionInterface
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
*/
public function testGetCollectionOperativeSystem(): void
{
UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]);
OperativeSystemFactory::createMany(10);
$this->createClientWithCredentials()->request('GET', '/operative-systems');
$this->assertResponseStatusCodeSame(Response::HTTP_OK);
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
$this->assertJsonContains([
'@context' => '/contexts/OperativeSystem',
'@id' => '/operative-systems',
'@type' => 'hydra:Collection',
'hydra:totalItems' => 10,
]);
}
/**
* @throws RedirectionExceptionInterface
* @throws DecodingExceptionInterface
* @throws ClientExceptionInterface
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
*/
public function testCreateOperativeSystem(): void
{
UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]);
$this->createClientWithCredentials()->request('POST', '/operative-systems',['json' => [
'name' => self::OS_CREATE,
]]);
$this->assertResponseStatusCodeSame(201);
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
$this->assertJsonContains([
'@context' => '/contexts/OperativeSystemOutput',
'@type' => 'OperativeSystem',
'name' => self::OS_CREATE
]);
}
/**
* @throws RedirectionExceptionInterface
* @throws DecodingExceptionInterface
* @throws ClientExceptionInterface
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
*/
public function testUpdateOperativeSystem(): void
{
UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]);
OperativeSystemFactory::createOne(['name' => self::OS_CREATE]);
$iri = $this->findIriBy(OperativeSystem::class, ['name' => self::OS_CREATE]);
$this->createClientWithCredentials()->request('PUT', $iri, ['json' => [
'name' => self::OS_UPDATE,
]]);
$this->assertResponseIsSuccessful();
$this->assertJsonContains([
'@id' => $iri,
'name' => self::OS_UPDATE,
]);
}
/**
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
* @throws RedirectionExceptionInterface
* @throws DecodingExceptionInterface
* @throws ClientExceptionInterface
*/
public function testDeleteOperativeSystem(): void
{
UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]);
OperativeSystemFactory::createOne(['name' => self::OS_DELETE]);
$iri = $this->findIriBy(OperativeSystem::class, ['name' => self::OS_DELETE]);
$this->createClientWithCredentials()->request('DELETE', $iri);
$this->assertResponseStatusCodeSame(204);
$this->assertNull(
static::getContainer()->get('doctrine')->getRepository(OperativeSystem::class)->findOneBy(['name' => self::OS_DELETE])
);
}
}

View File

@ -2,9 +2,16 @@
namespace Functional;
use App\Entity\Client;
use App\Entity\Menu;
use App\Entity\Partition;
use App\Factory\ClientFactory;
use App\Factory\HardwareProfileFactory;
use App\Factory\MenuFactory;
use App\Factory\OrganizationalUnitFactory;
use App\Factory\PartitionFactory;
use App\Factory\UserFactory;
use App\Model\OrganizationalUnitTypes;
use App\Model\UserGroupPermissions;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
@ -16,9 +23,9 @@ use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
class PartitionTest extends AbstractTest
{
CONST string USER_ADMIN = 'ogadmin';
CONST string PARTITION_CREATE = 'test-partition-create';
CONST string PARTITION_UPDATE = 'test-partition-update';
CONST string PARTITION_DELETE = 'test-partition-delete';
CONST string CLIENT_CREATE = 'test-client-create';
const string HW_PROFILE = 'HW Test';
/**
* @throws RedirectionExceptionInterface
@ -31,7 +38,12 @@ class PartitionTest extends AbstractTest
{
UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]);
PartitionFactory::createMany(10);
$ou = OrganizationalUnitFactory::createOne(['type' => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT]);
$hp = HardwareProfileFactory::createOne(['description' => self::HW_PROFILE]);
$client = ClientFactory::createOne(['name' => self::CLIENT_CREATE, 'serialNumber' => '123abc', 'organizationalUnit' => $ou, 'hardwareProfile' => $hp]);
PartitionFactory::createMany(10, ['client' => $client]);
$this->createClientWithCredentials()->request('GET', '/partitions');
$this->assertResponseStatusCodeSame(Response::HTTP_OK);
@ -43,4 +55,40 @@ class PartitionTest extends AbstractTest
'hydra:totalItems' => 10,
]);
}
/**
* @throws RedirectionExceptionInterface
* @throws DecodingExceptionInterface
* @throws ClientExceptionInterface
* @throws TransportExceptionInterface
* @throws ServerExceptionInterface
*/
public function testCreatePartition(): void
{
UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]);
$ou = OrganizationalUnitFactory::createOne(['type' => OrganizationalUnitTypes::ORGANIZATIONAL_UNIT]);
$hp = HardwareProfileFactory::createOne(['description' => self::HW_PROFILE]);
ClientFactory::createOne(['name' => self::CLIENT_CREATE, 'serialNumber' => '123abc', 'organizationalUnit' => $ou, 'hardwareProfile' => $hp]);
$iri = $this->findIriBy(Client::class, ['name' => self::CLIENT_CREATE]);
$this->createClientWithCredentials()->request('POST', '/partitions',['json' => [
'size' => 100,
'osName' => 'Ubuntu',
'client' => $iri,
'memoryUsage' => 100
]]);
$this->assertResponseStatusCodeSame(201);
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
$this->assertJsonContains([
'@context' => '/contexts/PartitionOutput',
'@type' => 'Partition',
'size' => 100,
'osName' => 'Ubuntu',
'memoryUsage' => 100
]);
}
}