Implement Keystone environment deployments
This commit is contained in:
@@ -2,18 +2,23 @@
|
||||
|
||||
namespace App\Jobs\Services;
|
||||
|
||||
use App\Enums\DeploymentStatus;
|
||||
use App\Actions\Services\ResolveServiceImageDigest;
|
||||
use App\Data\Operations\PlannedStep;
|
||||
use App\Enums\OperationKind;
|
||||
use App\Enums\OperationStatus;
|
||||
use App\Enums\ServiceStatus;
|
||||
use App\Models\Deployment;
|
||||
use App\Models\Operation;
|
||||
use App\Models\Service;
|
||||
use App\Services\Compose\ComposeRenderer;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Queue\Queueable;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class DeployService implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
protected Deployment $deployment;
|
||||
protected Operation $operation;
|
||||
|
||||
public function __construct(
|
||||
public Service $service,
|
||||
@@ -24,20 +29,26 @@ class DeployService implements ShouldQueue
|
||||
public function handle(): void
|
||||
{
|
||||
$driver = $this->service->driver();
|
||||
$this->service->forceFill([
|
||||
'available_image_digest' => app(ResolveServiceImageDigest::class)->execute($this->service),
|
||||
])->save();
|
||||
$this->service->update([
|
||||
'status' => ServiceStatus::INSTALLING,
|
||||
]);
|
||||
$this->deployment = $this->service->deployments()->create([
|
||||
'status' => DeploymentStatus::PENDING,
|
||||
$this->operation = $this->service->operations()->create([
|
||||
'kind' => OperationKind::SERVICE_DEPLOY,
|
||||
'status' => OperationStatus::PENDING,
|
||||
]);
|
||||
$deploymentPlan = $driver->getDeploymentPlan($this->deployment->hash);
|
||||
foreach ($deploymentPlan->steps as $index => $plannedStep) {
|
||||
$step = $this->deployment->steps()->create([
|
||||
$operationPlan = $driver->getOperationPlan($this->operation->hash);
|
||||
$steps = $this->stepsWithComposeUpload($operationPlan->steps);
|
||||
|
||||
foreach ($steps as $index => $plannedStep) {
|
||||
$step = $this->operation->steps()->create([
|
||||
'name' => $plannedStep->name,
|
||||
'order' => $index + 1,
|
||||
'status' => DeploymentStatus::PENDING,
|
||||
'script' => $plannedStep->getSafeScript(),
|
||||
'secrets' => $this->service->credentials,
|
||||
'status' => OperationStatus::PENDING,
|
||||
'script' => $plannedStep->getScriptTemplate(),
|
||||
'secrets' => $plannedStep->secrets(),
|
||||
]);
|
||||
if ($index === 0) {
|
||||
$step->dispatchJob();
|
||||
@@ -45,11 +56,45 @@ class DeployService implements ShouldQueue
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, \App\Data\Operations\PlannedStep> $steps
|
||||
* @return array<int, \App\Data\Operations\PlannedStep>
|
||||
*/
|
||||
private function stepsWithComposeUpload(array $steps): array
|
||||
{
|
||||
try {
|
||||
$renderer = app(ComposeRenderer::class);
|
||||
$compose = $renderer->render($this->service);
|
||||
$env = $renderer->renderEnvironmentFile($this->service);
|
||||
} catch (InvalidArgumentException) {
|
||||
return $steps;
|
||||
}
|
||||
|
||||
return [
|
||||
new PlannedStep(
|
||||
name: 'Upload Compose file',
|
||||
script: $this->composeUploadScript($compose, $env),
|
||||
),
|
||||
...$steps,
|
||||
];
|
||||
}
|
||||
|
||||
private function composeUploadScript(string $compose, string $env): string
|
||||
{
|
||||
$servicePath = "/home/keystone/services/{$this->service->id}";
|
||||
|
||||
return implode("\n", [
|
||||
"mkdir -p {$servicePath}",
|
||||
'printf %s '.escapeshellarg(base64_encode($compose))." | base64 -d > {$servicePath}/compose.yml",
|
||||
'printf %s '.escapeshellarg(base64_encode($env))." | base64 -d > {$servicePath}/.env",
|
||||
]);
|
||||
}
|
||||
|
||||
public function failed(\Throwable $exception): void
|
||||
{
|
||||
if (isset($this->deployment)) {
|
||||
$this->deployment->update([
|
||||
'status' => DeploymentStatus::FAILED,
|
||||
if (isset($this->operation)) {
|
||||
$this->operation->update([
|
||||
'status' => OperationStatus::FAILED,
|
||||
]);
|
||||
$this->service->update([
|
||||
'status' => ServiceStatus::ERROR,
|
||||
|
||||
Reference in New Issue
Block a user