diff --git a/app/Livewire/GlobalSearch.php b/app/Livewire/GlobalSearch.php index 531b6a5a63..c9a0aaed7f 100644 --- a/app/Livewire/GlobalSearch.php +++ b/app/Livewire/GlobalSearch.php @@ -207,6 +207,7 @@ class GlobalSearch extends Component 'new mysql' => 'mysql', 'new mariadb' => 'mariadb', 'new redis' => 'redis', + 'new valkey' => 'redis', 'new keydb' => 'keydb', 'new dragonfly' => 'dragonfly', 'new sqlite' => 'sqlite', @@ -477,7 +478,7 @@ class GlobalSearch extends Component 'link' => $db->link(), 'project' => $db->environment->project->name ?? null, 'environment' => $db->environment->name ?? null, - 'search_text' => strtolower($db->name.' '.$db->uuid.' redis '.$db->description.' database databases db'), + 'search_text' => strtolower($db->name.' '.$db->uuid.' redis valkey '.$db->description.' database databases db'), ]; }) ); @@ -1324,12 +1325,12 @@ class GlobalSearch extends Component ]); $items->push([ - 'name' => 'Redis', - 'description' => 'In-memory data structure store', - 'quickcommand' => '(type: new redis)', + 'name' => 'Redis / Valkey', + 'description' => 'In-memory data structure store (Redis or Valkey)', + 'quickcommand' => '(type: new redis or new valkey)', 'type' => 'redis', 'category' => 'Databases', - 'logo' => 'svgs/redis.svg', + 'logo' => 'svgs/resources/redis-valkey.svg', 'resourceType' => 'database', ]); diff --git a/app/Livewire/Project/Database/Redis/StatusInfo.php b/app/Livewire/Project/Database/Redis/StatusInfo.php index 2e784e2c09..ca1079285f 100644 --- a/app/Livewire/Project/Database/Redis/StatusInfo.php +++ b/app/Livewire/Project/Database/Redis/StatusInfo.php @@ -16,6 +16,6 @@ class StatusInfo extends Component protected function databaseLabel(): string { - return 'Redis'; + return 'Redis / Valkey'; } } diff --git a/app/Livewire/Project/New/Select.php b/app/Livewire/Project/New/Select.php index f000496387..021f81fb0a 100644 --- a/app/Livewire/Project/New/Select.php +++ b/app/Livewire/Project/New/Select.php @@ -38,6 +38,12 @@ class Select extends Component public Collection|array $allServices = []; + /** Database types that ask for an image before the database is created. */ + private const DATABASE_IMAGE_STEPS = [ + 'postgresql' => 'select-postgresql-type', + 'redis' => 'select-redis-type', + ]; + public bool $isDatabase = false; public bool $includeSwarm = true; @@ -50,8 +56,6 @@ class Select extends Component public ?string $selectedEnvironment = null; - public string $postgresql_type = 'postgres:18-alpine'; - public ?string $existingPostgresqlUrl = null; protected $queryString = [ @@ -72,20 +76,21 @@ class Select extends Component $this->environments = $project->environments; $this->selectedEnvironment = $this->environments->where('uuid', data_get($this->parameters, 'environment_uuid'))->firstOrFail()->name; - // Check if we have all required params for PostgreSQL type selection + // Check if we have all required params for the database image step // This handles navigation from global search $queryType = request()->query('type'); $queryServerId = request()->query('server_id'); $queryDestination = request()->query('destination'); + $imageStep = self::DATABASE_IMAGE_STEPS[$queryType] ?? null; - if ($queryType === 'postgresql' && $queryServerId !== null && $queryDestination) { + if ($imageStep && $queryServerId !== null && $queryDestination) { $server = Server::isUsable()->whereKey($queryServerId)->first(); if ($server && $this->findDestination($server, $queryDestination)) { $this->type = $queryType; $this->server_id = $server->id; $this->destination_uuid = $queryDestination; $this->server = $server; - $this->current_step = 'select-postgresql-type'; + $this->current_step = $imageStep; } } } catch (\Exception $e) { @@ -235,9 +240,10 @@ class Select extends Component ], [ 'id' => 'redis', - 'name' => 'Redis', - 'description' => 'An in-memory key-value store used as a database, cache, and message broker.', - 'logo' => resource_logo_url('redis'), + 'name' => 'Redis / Valkey', + 'description' => 'An in-memory key-value store for caching, queues, and sessions.', + 'logo' => resource_logo_url('redis-valkey'), + 'logoDark' => resource_logo_url('redis-valkey-dark'), ], [ 'id' => 'keydb', @@ -484,24 +490,22 @@ class Select extends Component return $server->standaloneDockers->concat($server->swarmDockers)->firstWhere('uuid', $destinationUuid); } - public function setPostgresqlType(string $type) + public function setDatabaseImage(string $image) { - $this->postgresql_type = $type; - return redirect()->route('project.resource.create', [ 'project_uuid' => $this->parameters['project_uuid'], 'environment_uuid' => $this->parameters['environment_uuid'], 'type' => $this->type, 'destination' => $this->destination_uuid, 'server_id' => $this->server_id, - 'database_image' => $this->postgresql_type, + 'database_image' => $image, ]); } public function whatToDoNext() { - if ($this->type === 'postgresql') { - $this->current_step = 'select-postgresql-type'; + if (isset(self::DATABASE_IMAGE_STEPS[$this->type])) { + $this->current_step = self::DATABASE_IMAGE_STEPS[$this->type]; } else { return redirect()->route('project.resource.create', [ 'project_uuid' => $this->parameters['project_uuid'], diff --git a/app/Livewire/Project/Resource/Create.php b/app/Livewire/Project/Resource/Create.php index 25e589f657..21906b5889 100644 --- a/app/Livewire/Project/Resource/Create.php +++ b/app/Livewire/Project/Resource/Create.php @@ -52,7 +52,13 @@ class Create extends Component databaseImage: $database_image ); } elseif ($type->value() === 'redis') { - $database = create_standalone_redis($environment->id, $destination); + // Redis requires database_image (Redis or Valkey) to be explicitly set + if (! $database_image) { + $this->type = $type->value(); + + return; + } + $database = create_standalone_redis($environment->id, $destination, ['image' => $database_image]); } elseif ($type->value() === 'mongodb') { $database = create_standalone_mongodb($environment->id, $destination); } elseif ($type->value() === 'mysql') { diff --git a/app/Services/EnvironmentCanvas.php b/app/Services/EnvironmentCanvas.php index 6a7ffcea82..c0310dbf05 100644 --- a/app/Services/EnvironmentCanvas.php +++ b/app/Services/EnvironmentCanvas.php @@ -43,7 +43,7 @@ class EnvironmentCanvas private const DATABASE_ENGINE_NAMES = [ 'postgresql' => 'PostgreSQL', - 'redis' => 'Redis', + 'redis' => 'Redis / Valkey', 'mongodb' => 'MongoDB', 'mysql' => 'MySQL', 'mariadb' => 'MariaDB', diff --git a/public/svgs/resources/redis-valkey-dark.svg b/public/svgs/resources/redis-valkey-dark.svg new file mode 100644 index 0000000000..1b70ab6132 --- /dev/null +++ b/public/svgs/resources/redis-valkey-dark.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/svgs/resources/redis-valkey.svg b/public/svgs/resources/redis-valkey.svg new file mode 100644 index 0000000000..4dc437facd --- /dev/null +++ b/public/svgs/resources/redis-valkey.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/views/livewire/global-search.blade.php b/resources/views/livewire/global-search.blade.php index 89ed577f63..d789180cfc 100644 --- a/resources/views/livewire/global-search.blade.php +++ b/resources/views/livewire/global-search.blade.php @@ -257,7 +257,7 @@ 'new private github', 'new private gh', 'new private deploy', 'new deploy key', 'new dockerfile', 'new docker compose', 'new compose', 'new docker image', 'new image', 'new postgresql', 'new postgres', 'new mysql', 'new mariadb', - 'new redis', 'new keydb', 'new dragonfly', 'new mongodb', 'new mongo', 'new clickhouse', 'new sqlite' + 'new redis', 'new valkey', 'new keydb', 'new dragonfly', 'new mongodb', 'new mongo', 'new clickhouse', 'new sqlite' ]; if (this.scope === 'global' && exactMatchCommands.includes(trimmed)) { const matchingItem = this.creatableItems.find(item => { diff --git a/resources/views/livewire/project/database/redis/general.blade.php b/resources/views/livewire/project/database/redis/general.blade.php index 2517ba86ee..2026335a84 100644 --- a/resources/views/livewire/project/database/redis/general.blade.php +++ b/resources/views/livewire/project/database/redis/general.blade.php @@ -3,7 +3,7 @@ + description="Manage the identity, container image, and credentials of this Redis / Valkey database."> @@ -14,10 +14,10 @@
+ helper="Use a published Redis or Valkey image from Docker Hub, for example redis:7.2 or valkey/valkey:9-alpine." />
- + @if ($database->started_at) Changing values here does not update Redis. Update Redis first, then synchronize the values here so @@ -99,15 +99,15 @@ id="customDockerRunOptions" label="Custom Docker options" canGate="update" :canResource="$database" /> @endif - + @if ($isPasswordHiddenForMember) - + @else @endif diff --git a/resources/views/livewire/project/new/select.blade.php b/resources/views/livewire/project/new/select.blade.php index d8b6427769..326ab4b9ae 100644 --- a/resources/views/livewire/project/new/select.blade.php +++ b/resources/views/livewire/project/new/select.blade.php @@ -805,7 +805,7 @@
PostgreSQL 18
PostgreSQL 17
@@ -849,7 +849,7 @@
PostgreSQL 16
@@ -870,7 +870,7 @@
Supabase PostgreSQL
@@ -891,7 +891,7 @@
PostGIS
PGVector 18
@@ -935,7 +935,7 @@
PGVector 17
@@ -957,6 +957,60 @@
@endif + @if ($current_step === 'select-redis-type') +
+
+

Select a Redis or Valkey image

+

Both work with the same clients, commands, + and configuration.

+
+
+
+
+
Valkey 9 Default
+
+ An open-source (BSD) fork of Redis from the Linux Foundation. It works with all Redis clients. +
+
+ + + + + +
+
+
+
Redis 7.2
+
+ The original in-memory key-value store. +
+
+ + + + + +
+
+
+ @endif @if ($current_step === 'existing-postgresql')