Skip to content

Commit

Permalink
feat: #168 support rewrite rules
Browse files Browse the repository at this point in the history
  • Loading branch information
bohdan-shulha committed Sep 6, 2024
1 parent c148295 commit d4f0779
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 50 deletions.
2 changes: 2 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
set -e

php artisan ide-helper:actions
vendor/bin/pint _ide_helper_actions.php
git add _ide_helper_actions.php

lint-staged
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ RUN php composer.phar install \
&& apt-get -y remove npm unzip \
&& apt-get -y clean \
&& apt-get -y autoremove \
&& mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
&& mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \
&& echo "memory_limit = 256M" >> "$PHP_INI_DIR/php.ini"
26 changes: 8 additions & 18 deletions _ide_helper_actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@
* @method static dispatchAfterResponse(\App\Models\User $user, \App\Models\Node $node, string $advertiseAddr)
* @method static mixed run(\App\Models\User $user, \App\Models\Node $node, string $advertiseAddr)
*/
class InitCluster
{
}
class InitCluster {}

namespace App\Actions\Services;

/**
Expand All @@ -29,32 +28,23 @@ class InitCluster
* @method static dispatchAfterResponse(\App\Models\User $user, \App\Models\Service $service, \App\Models\DeploymentData $deploymentData)
* @method static \App\Models\Deployment run(\App\Models\User $user, \App\Models\Service $service, \App\Models\DeploymentData $deploymentData)
*/
class StartDeployment
{
}
class StartDeployment {}

namespace Lorisleiva\Actions\Concerns;

/**
* @method void asController()
*/
trait AsController
{
}
trait AsController {}
/**
* @method void asListener()
*/
trait AsListener
{
}
trait AsListener {}
/**
* @method void asJob()
*/
trait AsJob
{
}
trait AsJob {}
/**
* @method void asCommand(\Illuminate\Console\Command $command)
*/
trait AsCommand
{
}
trait AsCommand {}
61 changes: 39 additions & 22 deletions app/Models/Deployment.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,35 +113,52 @@ public function asNodeTasks(): array
$caddyHandlers[] = collect($process->caddy)->map(function (Caddy $caddy) use ($deployment, $process) {
$routes = [];

$handlers = [];

$pathRegexps = [];
foreach ($process->rewriteRules as $rewriteRule) {
$pathRegexps[] = [
'find' => $rewriteRule->pathFrom,
'replace' => $rewriteRule->pathTo,
];
}

if (! empty($pathRegexps)) {
$handlers[] = [
'handler' => 'rewrite',
'path_regexp' => $pathRegexps,
];
}

$handlers[] = [
'handler' => 'reverse_proxy',
'headers' => [
'request' => [
'set' => $this->getForwardedHeaders($caddy),
],
'response' => [
'set' => [
'X-Powered-By' => ['https://ptah.sh'],
'X-Ptah-Rule-Id' => [$caddy->id],
],
],
],
'transport' => $this->getTransportOptions($caddy, $process),
'upstreams' => [
[
'dial' => "{$process->name}.{$deployment->data->internalDomain}:{$caddy->targetPort}",
],
],
];

$routes[] = [
'match' => [
[
'host' => [$caddy->domain],
'path' => [$caddy->path],
],
],
'handle' => [
[
'handler' => 'reverse_proxy',
'headers' => [
'request' => [
'set' => $this->getForwardedHeaders($caddy),
],
'response' => [
'set' => [
'X-Powered-By' => ['https://ptah.sh'],
'X-Ptah-Rule-Id' => [$caddy->id],
],
],
],
'transport' => $this->getTransportOptions($caddy, $process),
'upstreams' => [
[
'dial' => "{$process->name}.{$deployment->data->internalDomain}:{$caddy->targetPort}",
],
],
],
],
'handle' => $handlers,
];

foreach ($process->redirectRules as $redirectRule) {
Expand Down
1 change: 1 addition & 0 deletions app/Models/DeploymentData.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public static function make(array $attributes): static
'caddy' => [],
'fastCgi' => null,
'redirectRules' => [],
'rewriteRules' => [],
];

$defaults = [
Expand Down
5 changes: 4 additions & 1 deletion app/Models/DeploymentData/Process.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ public function __construct(
public ?FastCgi $fastCgi,
#[DataCollectionOf(RedirectRule::class)]
/* @var RedirectRule[] */
public array $redirectRules
public array $redirectRules,
#[DataCollectionOf(RewriteRule::class)]
/* @var RewriteRule[] */
public array $rewriteRules
) {}

public function findVolume(string $id): ?Volume
Expand Down
14 changes: 14 additions & 0 deletions app/Models/DeploymentData/RewriteRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace App\Models\DeploymentData;

use Spatie\LaravelData\Data;

class RewriteRule extends Data
{
public function __construct(
public string $id,
public string $pathFrom,
public string $pathTo
) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
DB::update("
UPDATE deployments
SET data = jsonb_set(
data,
'{processes}',
(
SELECT jsonb_agg(
process || jsonb_build_object('rewriteRules', '[]'::jsonb)
)
FROM jsonb_array_elements(data -> 'processes') AS process
)
)
");
}

/**
* Reverse the migrations.
*/
public function down(): void
{
DB::update("
UPDATE deployments
SET data = jsonb_set(
data,
'{processes}',
(
SELECT jsonb_agg(process - 'rewriteRules')
FROM jsonb_array_elements(data -> 'processes') AS process
)
)
");
}
};
75 changes: 68 additions & 7 deletions resources/js/Pages/Services/Partials/DeploymentData.vue
Original file line number Diff line number Diff line change
@@ -1,26 +1,19 @@
<script setup>
import InputError from "@/Components/InputError.vue";
import InputLabel from "@/Components/InputLabel.vue";
import PrimaryButton from "@/Components/PrimaryButton.vue";
import AppLayout from "@/Layouts/AppLayout.vue";
import TextInput from "@/Components/TextInput.vue";
import ActionSection from "@/Components/ActionSection.vue";
import { useForm } from "@inertiajs/vue3";
import FormField from "@/Components/FormField.vue";
import Select from "@/Components/Select.vue";
import SecondaryButton from "@/Components/SecondaryButton.vue";
import TextArea from "@/Components/TextArea.vue";
import { computed, effect, nextTick, reactive, ref } from "vue";
import ServiceDetailsForm from "@/Pages/Services/Partials/ServiceDetailsForm.vue";
import TabItem from "@/Components/Tabs/TabItem.vue";
import { FwbToggle, FwbTooltip } from "flowbite-vue";
import ProcessTabs from "@/Pages/Services/Partials/ProcessTabs.vue";
import DangerButton from "@/Components/DangerButton.vue";
import DialogModal from "@/Components/DialogModal.vue";
import AddComponentButton from "@/Components/Service/AddComponentButton.vue";
import RemoveComponentButton from "@/Components/Service/RemoveComponentButton.vue";
import ComponentBlock from "@/Components/Service/ComponentBlock.vue";
import FormFieldGrid from "@/Components/FormFieldGrid.vue";
import BackupSchedule from "@/Components/BackupSchedule.vue";
const model = defineModel();
Expand Down Expand Up @@ -122,6 +115,16 @@ const addRedirectRule = () => {
});
};
const addRewriteRule = () => {
model.value.processes[
state.selectedProcessIndex["caddy"]
].rewriteRules.push({
id: makeId("rewrite-rule"),
pathFrom: "",
pathTo: "",
});
};
const addFastCgiVar = () => {
model.value.processes[state.selectedProcessIndex["caddy"]].fastCgi.env.push(
{ id: makeId("fastcgi"), name: "", value: "" },
Expand Down Expand Up @@ -154,6 +157,7 @@ const addProcess = () => {
replicas: 1,
caddy: [],
redirectRules: [],
rewriteRules: [],
fastCgi: null,
});
Expand Down Expand Up @@ -1987,6 +1991,54 @@ const extractFieldErrors = (basePath) => {
/>
</FormField>
</ComponentBlock>

<ComponentBlock
v-model="
model.processes[state.selectedProcessIndex['caddy']]
.rewriteRules
"
v-slot="{ item }"
label="Rewrite Rules"
@remove="
model.processes[
state.selectedProcessIndex['caddy']
].rewriteRules.splice($event, 1)
"
>
<FormField
:error="
props.errors[
`processes.${state.selectedProcessIndex['caddy']}.rewriteRules.${item.$index}.pathFrom`
]
"
class="col-span-3"
>
<template #label>Path From</template>

<TextInput
v-model="item.pathFrom"
class="w-full"
placeholder="/old-path/(.*)"
/>
</FormField>

<FormField
:error="
props.errors[
`processes.${state.selectedProcessIndex['caddy']}.rewriteRules.${item.$index}.pathTo`
]
"
class="col-span-3"
>
<template #label>Path To</template>

<TextInput
v-model="item.pathTo"
class="w-full"
placeholder="/new-path/$1"
/>
</FormField>
</ComponentBlock>
</div>

<template v-if="hasFastCgiHandlers">
Expand Down Expand Up @@ -2142,6 +2194,15 @@ const extractFieldErrors = (basePath) => {
>
Redirect Rule
</AddComponentButton>
<AddComponentButton
v-if="
model.processes[state.selectedProcessIndex['caddy']].caddy
.length > 0
"
@click="addRewriteRule"
>
Rewrite Rule
</AddComponentButton>
<SecondaryButton v-if="hasFastCgiHandlers" @click="addFastCgiVar">
<svg
class="w-4 h-4 me-2 -ms-1 text-gray-800 dark:text-white"
Expand Down
9 changes: 8 additions & 1 deletion resources/js/Pages/Services/Partials/DynamicForm.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script setup>
import { computed } from "vue";
import TextInput from "@/Components/TextInput.vue";
import TextArea from "@/Components/TextArea.vue";
import FormField from "@/Components/FormField.vue";
const props = defineProps({
Expand Down Expand Up @@ -47,7 +48,13 @@ const itemName = computed(() => {
<template #label>{{ item.label }}</template>

<TextInput
v-if="item.type === 'text-field'"
v-if="item.type === 'text-field' && !item.multiline"
v-model="form[itemName]"
class="w-full"
/>

<TextArea
v-else-if="item.type === 'text-field' && item.multiline"
v-model="form[itemName]"
class="w-full"
/>
Expand Down

0 comments on commit d4f0779

Please sign in to comment.