feat: clone to env

This commit is contained in:
Andras Bacsai 2024-02-04 16:54:12 +01:00
parent 60f590454d
commit 1d59383c78
3 changed files with 50 additions and 36 deletions

View File

@ -22,12 +22,12 @@ class CloneMe extends Component
public ?int $selectedDestination = null; public ?int $selectedDestination = null;
public ?Server $server = null; public ?Server $server = null;
public $resources = []; public $resources = [];
public string $newProjectName = ''; public string $newName = '';
protected $messages = [ protected $messages = [
'selectedServer' => 'Please select a server.', 'selectedServer' => 'Please select a server.',
'selectedDestination' => 'Please select a server & destination.', 'selectedDestination' => 'Please select a server & destination.',
'newProjectName' => 'Please enter a name for the new project.', 'newName' => 'Please enter a name for the new project or environment.',
]; ];
public function mount($project_uuid) public function mount($project_uuid)
{ {
@ -36,7 +36,7 @@ public function mount($project_uuid)
$this->environment = $this->project->environments->where('name', $this->environment_name)->first(); $this->environment = $this->project->environments->where('name', $this->environment_name)->first();
$this->project_id = $this->project->id; $this->project_id = $this->project->id;
$this->servers = currentTeam()->servers; $this->servers = currentTeam()->servers;
$this->newProjectName = str($this->project->name . '-clone-' . (string)new Cuid2(7))->slug(); $this->newName = str($this->project->name . '-clone-' . (string)new Cuid2(7))->slug();
} }
public function render() public function render()
@ -46,34 +46,50 @@ public function render()
public function selectServer($server_id, $destination_id) public function selectServer($server_id, $destination_id)
{ {
if ($server_id == $this->selectedServer && $destination_id == $this->selectedDestination) {
$this->selectedServer = null;
$this->selectedDestination = null;
$this->server = null;
return;
}
$this->selectedServer = $server_id; $this->selectedServer = $server_id;
$this->selectedDestination = $destination_id; $this->selectedDestination = $destination_id;
$this->server = $this->servers->where('id', $server_id)->first(); $this->server = $this->servers->where('id', $server_id)->first();
} }
public function clone() public function clone(string $type)
{ {
try { try {
$this->validate([ $this->validate([
'selectedDestination' => 'required', 'selectedDestination' => 'required',
'newProjectName' => 'required', 'newName' => 'required',
]); ]);
$foundProject = Project::where('name', $this->newProjectName)->first(); if ($type === 'project') {
if ($foundProject) { $foundProject = Project::where('name', $this->newName)->first();
throw new \Exception('Project with the same name already exists.'); if ($foundProject) {
} throw new \Exception('Project with the same name already exists.');
$newProject = Project::create([ }
'name' => $this->newProjectName, $project = Project::create([
'team_id' => currentTeam()->id, 'name' => $this->newName,
'description' => $this->project->description . ' (clone)', 'team_id' => currentTeam()->id,
]); 'description' => $this->project->description . ' (clone)',
if ($this->environment->name !== 'production') { ]);
$newProject->environments()->create([ if ($this->environment->name !== 'production') {
'name' => $this->environment->name, $project->environments()->create([
'name' => $this->environment->name,
]);
}
$environment = $project->environments->where('name', $this->environment->name)->first();
} else {
$foundEnv = $this->project->environments()->where('name', $this->newName)->first();
if ($foundEnv) {
throw new \Exception('Environment with the same name already exists.');
}
$project = $this->project;
$environment = $this->project->environments()->create([
'name' => $this->newName,
]); ]);
} }
$newEnvironment = $newProject->environments->where('name', $this->environment->name)->first();
// Clone Applications
$applications = $this->environment->applications; $applications = $this->environment->applications;
$databases = $this->environment->databases(); $databases = $this->environment->databases();
$services = $this->environment->services; $services = $this->environment->services;
@ -83,7 +99,7 @@ public function clone()
'uuid' => $uuid, 'uuid' => $uuid,
'fqdn' => generateFqdn($this->server, $uuid), 'fqdn' => generateFqdn($this->server, $uuid),
'status' => 'exited', 'status' => 'exited',
'environment_id' => $newEnvironment->id, 'environment_id' => $environment->id,
// This is not correct, but we need to set it to something // This is not correct, but we need to set it to something
'destination_id' => $this->selectedDestination, 'destination_id' => $this->selectedDestination,
]); ]);
@ -110,7 +126,7 @@ public function clone()
'uuid' => $uuid, 'uuid' => $uuid,
'status' => 'exited', 'status' => 'exited',
'started_at' => null, 'started_at' => null,
'environment_id' => $newEnvironment->id, 'environment_id' => $environment->id,
'destination_id' => $this->selectedDestination, 'destination_id' => $this->selectedDestination,
]); ]);
$newDatabase->save(); $newDatabase->save();
@ -136,7 +152,7 @@ public function clone()
$uuid = (string)new Cuid2(7); $uuid = (string)new Cuid2(7);
$newService = $service->replicate()->fill([ $newService = $service->replicate()->fill([
'uuid' => $uuid, 'uuid' => $uuid,
'environment_id' => $newEnvironment->id, 'environment_id' => $environment->id,
'destination_id' => $this->selectedDestination, 'destination_id' => $this->selectedDestination,
]); ]);
$newService->save(); $newService->save();
@ -153,8 +169,8 @@ public function clone()
$newService->parse(); $newService->parse();
} }
return redirect()->route('project.resource.index', [ return redirect()->route('project.resource.index', [
'project_uuid' => $newProject->uuid, 'project_uuid' => $project->uuid,
'environment_name' => $newEnvironment->name, 'environment_name' => $environment->name,
]); ]);
} catch (\Exception $e) { } catch (\Exception $e) {
return handleError($e, $this); return handleError($e, $this);

View File

@ -76,7 +76,7 @@ .icon:hover {
} }
.box { .box {
@apply flex p-2 transition-colors cursor-pointer min-h-[4rem] bg-coolgray-100 hover:bg-coollabs-100 hover:text-white hover:no-underline min-w-[24rem]; @apply flex p-2 transition-colors cursor-pointer min-h-[4rem] bg-coolgray-100 hover:bg-coollabs-100 hover:text-white hover:no-underline;
} }
.box-without-bg { .box-without-bg {

View File

@ -1,19 +1,17 @@
<form wire:submit='clone'> <form>
<div class="flex flex-col"> <div class="flex flex-col">
<h1>Clone</h1> <h1>Clone</h1>
<div class="subtitle ">Quickly clone all resources to a new project</div> <div class="subtitle ">Quickly clone all resources to a new project or environment</div>
</div>
<div class="flex items-end gap-2">
<x-forms.input required id="newProjectName" label="New Project Name" />
<x-forms.button isHighlighted type="submit">Clone</x-forms.button>
</div> </div>
<x-forms.input required id="newName" label="New Name" />
<x-forms.button isHighlighted wire:click="clone('project')" class="mt-4">Clone to a new Project</x-forms.button>
<x-forms.button isHighlighted wire:click="clone('environment')" class="mt-4">Clone to a new Environment</x-forms.button>
<h3 class="pt-4 pb-2">Servers</h3> <h3 class="pt-4 pb-2">Servers</h3>
<div>Choose the server and network to clone the resources to.</div> <div>Choose the server and network to clone the resources to.</div>
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
@foreach ($servers->sortBy('id') as $server) @foreach ($servers->sortBy('id') as $server)
<div class="p-4"> <div class="p-4">
<h4>{{ $server->name }}</h4> <h4>{{ $server->name }}</h4>
<h5>{{ $server->description }}</h5>
<div class="pt-4 pb-2">Docker Networks</div> <div class="pt-4 pb-2">Docker Networks</div>
<div class="grid grid-cols-1 gap-2 pb-4 lg:grid-cols-4"> <div class="grid grid-cols-1 gap-2 pb-4 lg:grid-cols-4">
@foreach ($server->destinations() as $destination) @foreach ($server->destinations() as $destination)
@ -30,9 +28,9 @@
<h3 class="pt-4 pb-2">Resources</h3> <h3 class="pt-4 pb-2">Resources</h3>
<div>These will be cloned to the new project</div> <div>These will be cloned to the new project</div>
<div class="grid grid-cols-1 gap-2 p-4 "> <div class="grid grid-cols-1 gap-2 pt-4 opacity-95 lg:grid-cols-2 xl:grid-cols-3">
@foreach ($environment->applications->sortBy('name') as $application) @foreach ($environment->applications->sortBy('name') as $application)
<div> <div class="cursor-default box-without-bg bg-coolgray-100 group">
<div class="flex flex-col"> <div class="flex flex-col">
<div class="font-bold text-white">{{ $application->name }}</div> <div class="font-bold text-white">{{ $application->name }}</div>
<div class="description">{{ $application->description }}</div> <div class="description">{{ $application->description }}</div>
@ -40,7 +38,7 @@
</div> </div>
@endforeach @endforeach
@foreach ($environment->databases()->sortBy('name') as $database) @foreach ($environment->databases()->sortBy('name') as $database)
<div> <div class="cursor-default box-without-bg bg-coolgray-100 group">
<div class="flex flex-col"> <div class="flex flex-col">
<div class="font-bold text-white">{{ $database->name }}</div> <div class="font-bold text-white">{{ $database->name }}</div>
<div class="description">{{ $database->description }}</div> <div class="description">{{ $database->description }}</div>
@ -48,7 +46,7 @@
</div> </div>
@endforeach @endforeach
@foreach ($environment->services->sortBy('name') as $service) @foreach ($environment->services->sortBy('name') as $service)
<div> <div class="cursor-default box-without-bg bg-coolgray-100 group">
<div class="flex flex-col"> <div class="flex flex-col">
<div class="font-bold text-white">{{ $service->name }}</div> <div class="font-bold text-white">{{ $service->name }}</div>
<div class="description">{{ $service->description }}</div> <div class="description">{{ $service->description }}</div>