99 lines
3.1 KiB
PHP
99 lines
3.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Labs;
|
|
|
|
use Illuminate\Support\Facades\File;
|
|
use RuntimeException;
|
|
use Symfony\Component\Yaml\Yaml;
|
|
|
|
/**
|
|
* Lit le lab.yaml d'un lab (voir paillasse-contenus/README.md pour le
|
|
* format) : topologie pour GenerateurTemplateHeat, vérifications pour la
|
|
* correction.
|
|
*/
|
|
class DefinitionLab
|
|
{
|
|
public readonly string $identifiant;
|
|
|
|
public readonly string $titre;
|
|
|
|
public readonly ?string $niveau;
|
|
|
|
public readonly ?int $dureeMin;
|
|
|
|
/** @var array<int, array{nom: string, cidr: string}> */
|
|
public readonly array $reseaux;
|
|
|
|
/** @var array<int, array{nom: string, image: string, flavor: string, reseaux: array<int, string>, preparation: ?string}> */
|
|
public readonly array $machines;
|
|
|
|
/** @var array<int, array{id: string, titre: string, machine: string, points: int, message_echec: string, bonus: bool}> */
|
|
public readonly array $verifications;
|
|
|
|
public static function depuis(string $identifiantLab): self
|
|
{
|
|
if (! preg_match('/^[a-z0-9][a-z0-9-]*$/', $identifiantLab)) {
|
|
throw new RuntimeException("Identifiant de lab invalide : {$identifiantLab}");
|
|
}
|
|
|
|
$chemin = config('labs.dossier')."/{$identifiantLab}/lab.yaml";
|
|
|
|
if (! File::exists($chemin)) {
|
|
throw new RuntimeException("Lab introuvable : {$chemin}");
|
|
}
|
|
|
|
return new self(Yaml::parseFile($chemin));
|
|
}
|
|
|
|
/**
|
|
* @return array<int, string>
|
|
*/
|
|
public static function identifiantsDisponibles(): array
|
|
{
|
|
return collect(File::directories(config('labs.dossier')))
|
|
->map(fn (string $dossier) => basename($dossier))
|
|
->filter(fn (string $id) => File::exists(config('labs.dossier')."/{$id}/lab.yaml"))
|
|
->values()
|
|
->all();
|
|
}
|
|
|
|
public function nombreMachines(): int
|
|
{
|
|
return count($this->machines);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $donnees
|
|
*/
|
|
private function __construct(array $donnees)
|
|
{
|
|
$this->identifiant = $donnees['id'];
|
|
$this->titre = $donnees['titre'];
|
|
$this->niveau = $donnees['niveau'] ?? null;
|
|
$this->dureeMin = $donnees['duree_min'] ?? null;
|
|
$this->reseaux = $donnees['reseaux'];
|
|
$this->machines = array_map(
|
|
fn (array $m) => [
|
|
'nom' => $m['nom'],
|
|
'image' => $m['image'],
|
|
'flavor' => $m['flavor'],
|
|
'reseaux' => $m['reseaux'],
|
|
'preparation' => $m['preparation'] ?? null,
|
|
],
|
|
$donnees['machines'],
|
|
);
|
|
// Les commandes et le résultat attendu ne sont lus que par le
|
|
// correcteur, sur l'hyperviseur : le portail n'en a pas besoin.
|
|
$this->verifications = array_map(
|
|
fn (array $v) => [
|
|
'id' => $v['id'],
|
|
'titre' => $v['titre'],
|
|
'machine' => $v['machine'],
|
|
'points' => (int) ($v['points'] ?? 1),
|
|
'message_echec' => $v['message_echec'] ?? 'Vérification non réussie.',
|
|
'bonus' => str_starts_with($v['id'], 'bonus-'),
|
|
],
|
|
$donnees['verifications'] ?? [],
|
|
);
|
|
}
|
|
}
|