fix: docker image parser
This commit is contained in:
@@ -6,6 +6,7 @@ use App\Models\Application;
|
||||
use App\Models\Project;
|
||||
use App\Models\StandaloneDocker;
|
||||
use App\Models\SwarmDocker;
|
||||
use App\Services\DockerImageParser;
|
||||
use Livewire\Component;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
@@ -28,12 +29,10 @@ class DockerImage extends Component
|
||||
$this->validate([
|
||||
'dockerImage' => 'required',
|
||||
]);
|
||||
$image = str($this->dockerImage)->before(':');
|
||||
if (str($this->dockerImage)->contains(':')) {
|
||||
$tag = str($this->dockerImage)->after(':');
|
||||
} else {
|
||||
$tag = 'latest';
|
||||
}
|
||||
|
||||
$parser = new DockerImageParser;
|
||||
$parser->parse($this->dockerImage);
|
||||
|
||||
$destination_uuid = $this->query['destination'];
|
||||
$destination = StandaloneDocker::where('uuid', $destination_uuid)->first();
|
||||
if (! $destination) {
|
||||
@@ -53,8 +52,8 @@ class DockerImage extends Component
|
||||
'git_branch' => 'main',
|
||||
'build_pack' => 'dockerimage',
|
||||
'ports_exposes' => 80,
|
||||
'docker_registry_image_name' => $image,
|
||||
'docker_registry_image_tag' => $tag,
|
||||
'docker_registry_image_name' => $parser->getFullImageNameWithoutTag(),
|
||||
'docker_registry_image_tag' => $parser->getTag(),
|
||||
'environment_id' => $environment->id,
|
||||
'destination_id' => $destination->id,
|
||||
'destination_type' => $destination_class,
|
||||
|
74
app/Services/DockerImageParser.php
Normal file
74
app/Services/DockerImageParser.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
class DockerImageParser
|
||||
{
|
||||
private string $registryUrl = '';
|
||||
|
||||
private string $imageName = '';
|
||||
|
||||
private string $tag = 'latest';
|
||||
|
||||
public function parse(string $imageString): self
|
||||
{
|
||||
// First split by : to handle the tag, but be careful with registry ports
|
||||
$lastColon = strrpos($imageString, ':');
|
||||
$hasSlash = str_contains($imageString, '/');
|
||||
|
||||
// If the last colon appears after the last slash, it's a tag
|
||||
// Otherwise it might be a port in the registry URL
|
||||
if ($lastColon !== false && (! $hasSlash || $lastColon > strrpos($imageString, '/'))) {
|
||||
$mainPart = substr($imageString, 0, $lastColon);
|
||||
$this->tag = substr($imageString, $lastColon + 1);
|
||||
} else {
|
||||
$mainPart = $imageString;
|
||||
$this->tag = 'latest';
|
||||
}
|
||||
|
||||
// Split the main part by / to handle registry and image name
|
||||
$pathParts = explode('/', $mainPart);
|
||||
|
||||
// If we have more than one part and the first part contains a dot or colon
|
||||
// it's likely a registry URL
|
||||
if (count($pathParts) > 1 && (str_contains($pathParts[0], '.') || str_contains($pathParts[0], ':'))) {
|
||||
$this->registryUrl = array_shift($pathParts);
|
||||
$this->imageName = implode('/', $pathParts);
|
||||
} else {
|
||||
$this->imageName = $mainPart;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFullImageNameWithoutTag(): string
|
||||
{
|
||||
return $this->registryUrl.'/'.$this->imageName;
|
||||
}
|
||||
|
||||
public function getRegistryUrl(): string
|
||||
{
|
||||
return $this->registryUrl;
|
||||
}
|
||||
|
||||
public function getImageName(): string
|
||||
{
|
||||
return $this->imageName;
|
||||
}
|
||||
|
||||
public function getTag(): string
|
||||
{
|
||||
return $this->tag;
|
||||
}
|
||||
|
||||
public function toString(): string
|
||||
{
|
||||
$parts = [];
|
||||
if ($this->registryUrl) {
|
||||
$parts[] = $this->registryUrl;
|
||||
}
|
||||
$parts[] = $this->imageName;
|
||||
|
||||
return implode('/', $parts).':'.$this->tag;
|
||||
}
|
||||
}
|
94
tests/Unit/Services/DockerImageParserTest.php
Normal file
94
tests/Unit/Services/DockerImageParserTest.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit\Services;
|
||||
|
||||
use App\Services\DockerImageParser;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DockerImageParserTest extends TestCase
|
||||
{
|
||||
private DockerImageParser $parser;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->parser = new DockerImageParser;
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_parses_simple_image_name()
|
||||
{
|
||||
$this->parser->parse('nginx');
|
||||
|
||||
$this->assertEquals('', $this->parser->getRegistryUrl());
|
||||
$this->assertEquals('nginx', $this->parser->getImageName());
|
||||
$this->assertEquals('latest', $this->parser->getTag());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_parses_image_with_tag()
|
||||
{
|
||||
$this->parser->parse('nginx:1.19');
|
||||
|
||||
$this->assertEquals('', $this->parser->getRegistryUrl());
|
||||
$this->assertEquals('nginx', $this->parser->getImageName());
|
||||
$this->assertEquals('1.19', $this->parser->getTag());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_parses_image_with_organization()
|
||||
{
|
||||
$this->parser->parse('coollabs/coolify:latest');
|
||||
|
||||
$this->assertEquals('', $this->parser->getRegistryUrl());
|
||||
$this->assertEquals('coollabs/coolify', $this->parser->getImageName());
|
||||
$this->assertEquals('latest', $this->parser->getTag());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_parses_image_with_registry_url()
|
||||
{
|
||||
$this->parser->parse('ghcr.io/coollabs/coolify:v4');
|
||||
|
||||
$this->assertEquals('ghcr.io', $this->parser->getRegistryUrl());
|
||||
$this->assertEquals('coollabs/coolify', $this->parser->getImageName());
|
||||
$this->assertEquals('v4', $this->parser->getTag());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_parses_image_with_port_in_registry()
|
||||
{
|
||||
$this->parser->parse('localhost:5000/my-app:dev');
|
||||
|
||||
$this->assertEquals('localhost:5000', $this->parser->getRegistryUrl());
|
||||
$this->assertEquals('my-app', $this->parser->getImageName());
|
||||
$this->assertEquals('dev', $this->parser->getTag());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_parses_image_without_tag()
|
||||
{
|
||||
$this->parser->parse('ghcr.io/coollabs/coolify');
|
||||
|
||||
$this->assertEquals('ghcr.io', $this->parser->getRegistryUrl());
|
||||
$this->assertEquals('coollabs/coolify', $this->parser->getImageName());
|
||||
$this->assertEquals('latest', $this->parser->getTag());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_converts_back_to_string()
|
||||
{
|
||||
$originalString = 'ghcr.io/coollabs/coolify:v4';
|
||||
$this->parser->parse($originalString);
|
||||
|
||||
$this->assertEquals($originalString, $this->parser->toString());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function it_converts_to_string_with_default_tag()
|
||||
{
|
||||
$this->parser->parse('nginx');
|
||||
$this->assertEquals('nginx:latest', $this->parser->toString());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user