fix(engine): one host per public IP (unique constraint + validation)
Prevents two onboarding runs from fighting over the same physical server. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>feat/portal-design
parent
48ed5e7d34
commit
91e308efb0
|
|
@ -16,7 +16,7 @@ class HostCreate extends Component
|
|||
#[Validate('required|string|in:fsn,hel')]
|
||||
public string $datacenter = 'fsn';
|
||||
|
||||
#[Validate('required|ip')]
|
||||
#[Validate('required|ip|unique:hosts,public_ip')]
|
||||
public string $public_ip = '';
|
||||
|
||||
#[Validate('required|string|min:8')]
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class HostFactory extends Factory
|
|||
return [
|
||||
'name' => 'pve-test-'.$this->faker->unique()->numberBetween(1, 99999),
|
||||
'datacenter' => 'fsn',
|
||||
'public_ip' => $this->faker->ipv4(),
|
||||
'public_ip' => $this->faker->unique()->ipv4(),
|
||||
'status' => 'pending',
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
// One physical server = one host record: prevents two onboarding runs
|
||||
// from fighting over the same machine's SSH/WireGuard/token config.
|
||||
Schema::table('hosts', function (Blueprint $table) {
|
||||
$table->unique('public_ip');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('hosts', function (Blueprint $table) {
|
||||
$table->dropUnique(['public_ip']);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -58,6 +58,19 @@ it('creates a host and starts onboarding with an encrypted password', function (
|
|||
Queue::assertPushed(AdvanceRunJob::class);
|
||||
});
|
||||
|
||||
it('rejects a duplicate public ip', function () {
|
||||
Host::factory()->create(['public_ip' => '203.0.113.99']);
|
||||
|
||||
Livewire::actingAs(admin())
|
||||
->test(HostCreate::class)
|
||||
->set('name', 'pve-dup')
|
||||
->set('datacenter', 'fsn')
|
||||
->set('public_ip', '203.0.113.99')
|
||||
->set('root_password', 'supersecret')
|
||||
->call('save')
|
||||
->assertHasErrors(['public_ip']);
|
||||
});
|
||||
|
||||
it('validates the add-host form', function () {
|
||||
Livewire::actingAs(admin())
|
||||
->test(HostCreate::class)
|
||||
|
|
|
|||
Loading…
Reference in New Issue