Add managed registry provisioning, pruning, and readiness tracking
This commit is contained in:
@@ -57,7 +57,7 @@ it('creates a parent environment operation with child service deploy operations'
|
||||
->forProvider($provider->id)
|
||||
->forNetwork($network->id)
|
||||
->create();
|
||||
$application = Application::factory()->for($organisation)->create();
|
||||
$application = Application::factory()->for($organisation)->create(['name' => 'Keystone Test App']);
|
||||
generateDeployKey($application);
|
||||
$environment = Environment::factory()->for($application)->create();
|
||||
$service = Service::factory()->for($environment)->for($server)->create([
|
||||
@@ -113,7 +113,7 @@ it('creates replica route configure and gateway cutover child operations', funct
|
||||
->forProvider($provider->id)
|
||||
->forNetwork($network->id)
|
||||
->create();
|
||||
$application = Application::factory()->for($organisation)->create();
|
||||
$application = Application::factory()->for($organisation)->create(['name' => 'Keystone Test App']);
|
||||
generateDeployKey($application);
|
||||
$environment = Environment::factory()->for($application)->create();
|
||||
$web = Service::factory()->for($environment)->for($server)->create([
|
||||
@@ -191,6 +191,7 @@ it('creates replica route configure and gateway cutover child operations', funct
|
||||
->first();
|
||||
|
||||
$serviceDeploy = $parent->children()->where('kind', OperationKind::SERVICE_DEPLOY)->first();
|
||||
$compose = renderedComposeFrom($serviceDeploy->steps()->where('name', 'Render Compose files')->first()->script, $web->id);
|
||||
|
||||
expect($serviceDeploy->children()->where('kind', OperationKind::REPLICA_DEPLOY)->count())->toBe(2)
|
||||
->and($parent->children()->where('kind', OperationKind::SLICE_CONFIGURE)->count())->toBe(1)
|
||||
@@ -203,6 +204,8 @@ it('creates replica route configure and gateway cutover child operations', funct
|
||||
->toContain('docker pull')
|
||||
->and($serviceDeploy->children()->where('kind', OperationKind::REPLICA_DEPLOY)->first()->steps()->where('name', 'Pull image for replica 1')->first()->script)
|
||||
->toContain('@sha256:deploymentdigest')
|
||||
->and($compose)
|
||||
->toContain('image: "registry.example.com/keystone-test-app:aaaaaaaaaaaa@sha256:deploymentdigest"')
|
||||
->and($serviceDeploy->children()->where('kind', OperationKind::REPLICA_DEPLOY)->first()->steps()->where('name', 'Health check replica 1')->first()->script)
|
||||
->toContain('health_status=')
|
||||
->and($parent->children()->where('kind', OperationKind::SLICE_CONFIGURE)->first()->steps()->first()->script)
|
||||
@@ -364,6 +367,80 @@ it('places desired replicas across configured server placements', function () {
|
||||
->toBe($servers->pluck('id')->all());
|
||||
});
|
||||
|
||||
it('renders compose and root registry auth on each managed registry replica server', function () {
|
||||
$organisation = Organisation::factory()->create();
|
||||
$provider = Provider::factory()->forOrganisation($organisation)->create();
|
||||
$network = Network::create([
|
||||
'organisation_id' => $organisation->id,
|
||||
'provider_id' => $provider->id,
|
||||
'name' => 'test-network',
|
||||
'ip_range' => '10.0.0.0/24',
|
||||
]);
|
||||
$servers = Server::factory()
|
||||
->count(2)
|
||||
->forOrganisation($organisation->id)
|
||||
->forProvider($provider->id)
|
||||
->forNetwork($network->id)
|
||||
->create();
|
||||
$servers[0]->update([
|
||||
'is_control_node' => true,
|
||||
'build_enabled' => true,
|
||||
]);
|
||||
$organisation->registries()->create([
|
||||
'name' => 'Managed',
|
||||
'type' => 'managed',
|
||||
'url' => 'registry.example.com',
|
||||
'credentials' => [
|
||||
'build_username' => 'keystone-build',
|
||||
'build_password' => 'build-secret',
|
||||
'runtime_username' => 'keystone-runtime',
|
||||
'runtime_password' => 'runtime-secret',
|
||||
],
|
||||
'control_server_id' => $servers[0]->id,
|
||||
'health_status' => 'healthy',
|
||||
'readiness_checks' => ['control_https' => 'passed', 'build_push' => 'passed'],
|
||||
'ready_at' => now(),
|
||||
]);
|
||||
$application = Application::factory()->for($organisation)->create(['name' => 'Keystone Test App']);
|
||||
generateDeployKey($application);
|
||||
$environment = Environment::factory()->for($application)->create();
|
||||
$service = Service::factory()->for($environment)->create([
|
||||
'organisation_id' => $organisation->id,
|
||||
'name' => 'web',
|
||||
'category' => ServiceCategory::APPLICATION,
|
||||
'type' => ServiceType::LARAVEL,
|
||||
'version' => 'php-8.4',
|
||||
'version_track' => 'php-8.4',
|
||||
'driver_name' => 'laravel.php-8.4',
|
||||
'deploy_policy' => DeployPolicy::WITH_ENVIRONMENT,
|
||||
'desired_replicas' => 2,
|
||||
'config' => [
|
||||
'server_ids' => $servers->pluck('id')->all(),
|
||||
],
|
||||
]);
|
||||
|
||||
(new DeployEnvironment($environment))->handle();
|
||||
|
||||
$serviceDeploy = $service->operations()
|
||||
->where('kind', OperationKind::SERVICE_DEPLOY)
|
||||
->firstOrFail();
|
||||
$replicaOperations = $serviceDeploy->children()
|
||||
->where('kind', OperationKind::REPLICA_DEPLOY)
|
||||
->with('steps')
|
||||
->get();
|
||||
|
||||
expect($replicaOperations)->toHaveCount(2)
|
||||
->and($replicaOperations[0]->steps->pluck('name')->all())->toContain('Render replica 1 Compose files')
|
||||
->and($replicaOperations[1]->steps->pluck('name')->all())->toContain('Render replica 2 Compose files');
|
||||
|
||||
$authStep = $replicaOperations[0]->steps->firstWhere('name', 'Configure registry auth for replica 1');
|
||||
|
||||
expect($authStep->script)->toContain("DOCKER_CONFIG='/root/.docker'")
|
||||
->and($authStep->script)->toContain('[!registry_password_base64!]')
|
||||
->and($authStep->script)->not->toContain('runtime-secret')
|
||||
->and($authStep->secrets['registry_password_base64'])->toBe(base64_encode('runtime-secret'));
|
||||
});
|
||||
|
||||
it('skips environment service operations when the target revision is already available', function () {
|
||||
$organisation = Organisation::factory()->create();
|
||||
$application = Application::factory()->for($organisation)->create();
|
||||
@@ -404,6 +481,17 @@ function generateDeployKey(Application $application): void
|
||||
]);
|
||||
}
|
||||
|
||||
function renderedComposeFrom(string $script, int $serviceId): string
|
||||
{
|
||||
preg_match(
|
||||
'/printf %s \'(?<encoded>[^\']+)\' \| base64 -d > \/home\/keystone\/services\/'.$serviceId.'\/compose\.yml/',
|
||||
$script,
|
||||
$matches,
|
||||
);
|
||||
|
||||
return base64_decode($matches['encoded'] ?? '', true) ?: '';
|
||||
}
|
||||
|
||||
it('blocks multi-server deploys that do not have a registry', function () {
|
||||
$organisation = Organisation::factory()->create();
|
||||
$application = Application::factory()->for($organisation)->create();
|
||||
|
||||
Reference in New Issue
Block a user