Skip to content

Commit

Permalink
Provisioning service (#1678)
Browse files Browse the repository at this point in the history
* fix(provisioning): Adding missing migration to ensure the uniqueness of server names at DB level

* feat: Add service and command for provisioning of servers

* feat(provisioning): Provision server pools

* feat(provisioning): Provision room types

* test(provisioning): Add tests for server provisioning

* impr(provisioning): Use Laravel validators for input validation

* test(provisioning): Add server deletion tests

* test(provisioning): Add server pool create + delete tests

* test(provisioning): Add room type create + delete tests

* feat(provisioning): Implement role provisioning

* feat(provisioning): Implement user provisioning

* feat(provisioning): Implemment settings provisioning

* test(provisioning): Add integration test for provisioning command

* impr(provisioning): Harden input validations

* doc(provisioning): Update changelog

* impr(provisioning): Use models' getLogLabel() function; add it where necessary

* impr(provisioning): Add helper function for creation log messages

* impr(provisioning): Make all role permissions optional

* doc(provisioning): Add documentation

* impr(provisioning): Use constructors to configure provisioners

* impr(provisioning): Optimize DB query in destroy wrapper function

* impr(provisioning): Simplify server status enum mapping

* clean(provisioning): Remove check made obsolete by input validation

* fix(provisioning): Repair "distinct" validations and add tests

* impr(ProvisionCommand): Wrap provisioning in DB transaction

* impr(provisioning): Properly validate user locale and timezone

* fix(provisioning): Sort permissions in user creation test

* impr(provisioning): Use UpdateSettings validation rules; fix test data

* impr(provisioning): Use constructor property promotion

* impr(provisioning): Enforce hex color

* doc(provision): Update and clarify documentation

* impr(provisioning): Use laravel prompt helpers for log messages

---------

Co-authored-by: Samuel Weirich <[email protected]>
  • Loading branch information
pizkaz and SamuelWei authored Jan 14, 2025
1 parent 13de37b commit 9f22ab9
Show file tree
Hide file tree
Showing 11 changed files with 1,391 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Environment variable for configuring restricted permissions that cannot be assigned to non-superuser roles ([#1651])
- Display raw permission names in the admin interface ([#1651])
- Visual tests with [Happo.io](https://happo.io) ([#1600])
- Artisan command for provisioning via JSON file ([#1636], [#1678])

### Changed

Expand Down
108 changes: 108 additions & 0 deletions app/Console/Commands/ProvisionCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<?php

namespace App\Console\Commands;

use App\Services\ProvisioningService;
use Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

use function Laravel\Prompts\error;
use function Laravel\Prompts\info;

class ProvisionCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'provision:all {path : path to a JSON file containing provisioning data}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Provision this PILOS instance';

public function __construct(protected ProvisioningService $provision)
{
parent::__construct();
}

/**
* Execute the console command.
*/
public function handle()
{
$data = json_decode(file_get_contents($this->argument('path')));

try {
DB::beginTransaction();

// Wipe existing data (order is important!)
if ($data->room_types->wipe) {
$this->provision->roomType->destroy();
}
if ($data->server_pools->wipe) {
$this->provision->serverPool->destroy();
}
if ($data->servers->wipe) {
$this->provision->server->destroy();
}
if ($data->roles->wipe) {
$this->provision->role->destroy();
}
if ($data->users->wipe) {
$this->provision->user->destroy();
}

// Add new instances
$n = count($data->servers->add);
info("Provisioning $n servers");
foreach ($data->servers->add as $item) {
$this->provision->server->create($item);
}

$n = count($data->server_pools->add);
info("Provisioning $n server pools");
foreach ($data->server_pools->add as $item) {
$this->provision->serverPool->create($item);
}

$n = count($data->room_types->add);
info("Provisioning $n room types");
foreach ($data->room_types->add as $item) {
$this->provision->roomType->create($item);
}

$n = count($data->roles->add);
info("Provisioning $n roles");
foreach ($data->roles->add as $item) {
$item->permissions = (array) $item->permissions;
$this->provision->role->create($item);
}

$n = count($data->users->add);
info("Provisioning $n users");
foreach ($data->users->add as $item) {
$this->provision->user->create($item);
}

$n = array_sum(array_map(fn ($v) => count(get_object_vars($v)), get_object_vars($data->settings)));
info("Provisioning $n settings");
foreach (get_object_vars($data->settings) as $section => $settings) {
$data->settings->{$section} = (array) $settings;
}
$this->provision->settings->set($data->settings);

DB::commit();
} catch (Exception $err) {
error("Provisioning failed, aborting transaction: {$err->getMessage()}");
DB::rollBack();

return 1;
}
}
}
5 changes: 5 additions & 0 deletions app/Models/Role.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,9 @@ public function scopeWithName(Builder $query, $name)
{
return $query->whereLike('name', '%'.$name.'%');
}

public function getLogLabel()
{
return $this->name.' ('.$this->id.')';
}
}
5 changes: 5 additions & 0 deletions app/Models/RoomType.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,9 @@ public function serverPool()
{
return $this->belongsTo(ServerPool::class);
}

public function getLogLabel()
{
return $this->name.' ('.$this->id.')';
}
}
5 changes: 5 additions & 0 deletions app/Models/ServerPool.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,9 @@ public function scopeWithName(Builder $query, $name)
{
return $query->whereLike('name', '%'.$name.'%');
}

public function getLogLabel()
{
return $this->name.' ('.$this->id.')';
}
}
Loading

0 comments on commit 9f22ab9

Please sign in to comment.