Skip to content

Commit

Permalink
feat: #16 install caddy as a part of the initialization process
Browse files Browse the repository at this point in the history
  • Loading branch information
bohdan-shulha committed Jun 23, 2024
1 parent 193c8ce commit 0c87788
Show file tree
Hide file tree
Showing 12 changed files with 144 additions and 23 deletions.
73 changes: 66 additions & 7 deletions app/Http/Controllers/SwarmTaskController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Http\Controllers;

use App\Http\Requests\NodeTask\InitClusterFormRequest;
use App\Models\DeploymentData;
use App\Models\Network;
use App\Models\Node;
use App\Models\NodeTaskGroup;
Expand All @@ -26,7 +27,7 @@ public function initCluster(InitClusterFormRequest $request)

$network = Network::create([
'swarm_id' => $swarm->id,
'name' => 'ptah-net',
'name' => dockerize_name('ptah-net'),
]);

$taskGroup = NodeTaskGroup::create([
Expand All @@ -36,7 +37,7 @@ public function initCluster(InitClusterFormRequest $request)
'invoker_id' => auth()->user()->id,
]);

$taskGroup->tasks()->createMany([
$tasks = [
[
'type' => NodeTaskType::InitSwarm,
'meta' => InitSwarmMeta::from([
Expand Down Expand Up @@ -64,7 +65,7 @@ public function initCluster(InitClusterFormRequest $request)
'type' => NodeTaskType::CreateNetwork,
'meta' => CreateNetworkMeta::from(['networkId' => $network->id, 'name' => $network->name]),
'payload' => [
'NetworkName' => $network->name,
'NetworkName' => $network->docker_name,
'NetworkCreateOptions' => [
'Driver' => 'overlay',
'Labels' => dockerize_labels([
Expand All @@ -73,10 +74,68 @@ public function initCluster(InitClusterFormRequest $request)
],
],
],
// TODO: create bare-bones Caddy
// [
// 'type' => NodeTaskType::CreateService,
// ]
];

$caddyService = $swarm->services()->create([
'name' => 'caddy',
]);

$deployment = $caddyService->deployments()->create([
'task_group_id' => $taskGroup->id,
'data' => DeploymentData::from([
'dockerRegistryId' => null,
'dockerImage' => 'caddy:2.8-alpine',
'envVars' => [
[
'name' => 'CADDY_ADMIN',
'value' => '0.0.0.0:2019',
]
],
'secretVars' => [],
'configFiles' => [
[
'path' => '/ptah/caddy/tls/.keep',
'content' => '# Keep this file',
]
],
'secretFiles' => [],
'volumes' => [
[
'name' => 'data',
'path' => '/data',
],
[
'name' => 'config',
'path' => '/config',
]
],
'networkName' => $network->docker_name,
'internalDomain' => 'caddy.ptah.local',
'ports' => [
[
'targetPort' => '80',
'publishedPort' => '80',
],
[
'targetPort' => '443',
'publishedPort' => '443',
],
[
'targetPort' => '2019',
'publishedPort' => '2019',
],
],
'replicas' => 1,
'placementNodeId' => null,
'caddy' => [],
'fastcgiVars' => [],
]),
]);

foreach ($deployment->asNodeTasks() as $task) {
$tasks[] = $task;
}

$taskGroup->tasks()->createMany($tasks);
}
}
3 changes: 2 additions & 1 deletion app/Models/Deployment.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ public function asNodeTasks(): array
],
'Networks' => [
[
'Target' => Network::find($data->networkId)->docker_id,
'Target' => $data->networkName,
'Aliases' => [$data->internalDomain],
]
],
Expand All @@ -203,6 +203,7 @@ public function asNodeTasks(): array
];
}

// TODO: update node labels and select by the labels instead of the id
protected function getNodeDockerId($nodeId)
{
return Node::find($nodeId)->docker_id;
Expand Down
2 changes: 1 addition & 1 deletion app/Models/DeploymentData.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public function __construct(
#[DataCollectionOf(Volume::class)]
/* @var Volume[] */
public array $volumes,
public int $networkId,
public string $networkName,
public string $internalDomain,
#[DataCollectionOf(NodePort::class)]
/* @var NodePort[] */
Expand Down
7 changes: 7 additions & 0 deletions app/Models/Network.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,11 @@ class Network extends Model
'swarm_id',
'name',
];

protected static function booted(): void
{
self::creating(function (Network $network) {
$network->docker_name = dockerize_name($network->name);
});
}
}
3 changes: 3 additions & 0 deletions app/Models/NodeTasks/AbstractTaskResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

namespace App\Models\NodeTasks;

use Illuminate\Database\Eloquent\Concerns\HasEvents;
use Spatie\LaravelData\Data;

abstract class AbstractTaskResult extends Data
{


abstract public function formattedHtml();
}
10 changes: 1 addition & 9 deletions app/Models/Service.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,7 @@ public function deployments(): HasMany

public function makeResourceName($name): string
{
$name = "svc_" . $this->id . '_'. $name;

$name = Str::snake($name);
$name = Str::replaceMatches('/\W/', '_', $name);
$name = Str::replaceMatches('/_+/', '_', $name);

if (Str::length($name) > 63) {
$name = Str::substr($name, 0, 57) . '_' . Str::random(5);
}
$name = dockerize_name("svc_" . $this->id . '_'. $name);

return $name;
}
Expand Down
6 changes: 6 additions & 0 deletions app/Models/Swarm.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Traits\HasOwningTeam;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Swarm extends Model
Expand All @@ -25,4 +26,9 @@ public function nodes(): HasMany
{
return $this->hasMany(Node::class);
}

public function services(): HasMany
{
return $this->hasMany(Service::class);
}
}
17 changes: 17 additions & 0 deletions bootstrap/helpers.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

use Illuminate\Support\Str;

if (!function_exists('dockerize_labels')) {
function dockerize_labels(array $labels): array
{
Expand All @@ -14,3 +16,18 @@ function dockerize_labels(array $labels): array
return $result;
}
}

if (!function_exists('dockerize_name')) {
function dockerize_name(string $name): string
{
$name = Str::snake($name);
$name = Str::replaceMatches('/\W/', '_', $name);
$name = Str::replaceMatches('/_+/', '_', $name);

if (Str::length($name) > 63) {
$name = Str::substr($name, 0, 57) . '_' . Str::random(5);
}

return $name;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('networks', function (Blueprint $table) {
$table->string('docker_name');
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('networks', function (Blueprint $table) {
$table->dropColumn('docker_name');
});
}
};
10 changes: 9 additions & 1 deletion resources/js/Pages/Nodes/Partials/AgentInstall.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import {onMounted, ref, reactive} from "vue";
import {CopyClipboard} from 'flowbite';
import InputLabel from "@/Components/InputLabel.vue";
defineProps({
'node': Object,
})
const trigger = ref(null);
const copyToClipboardRef = ref(null);
Expand Down Expand Up @@ -42,9 +46,13 @@ onMounted(() => {
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 17.345a4.76 4.76 0 0 0 2.558 1.618c2.274.589 4.512-.446 4.999-2.31.487-1.866-1.273-3.9-3.546-4.49-2.273-.59-4.034-2.623-3.547-4.488.486-1.865 2.724-2.899 4.998-2.31.982.236 1.87.793 2.538 1.592m-3.879 12.171V21m0-18v2.2"/>
</svg>
</div>
<!-- TODO: correct script -->
<!-- <input id="agent-install-cli" ref="copyToClipboardRef" type="text"-->
<!-- class="ps-10 p-2.5 col-span-6 bg-gray-50 border border-gray-300 text-gray-500 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full px-2.5 py-4 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500"-->
<!-- value="script cli goes here" disabled readonly>-->
<input id="agent-install-cli" ref="copyToClipboardRef" type="text"
class="ps-10 p-2.5 col-span-6 bg-gray-50 border border-gray-300 text-gray-500 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full px-2.5 py-4 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500"
value="script cli goes here" disabled readonly>
:value="$props.node.agent_token" disabled readonly>
</div>
<button ref="trigger"
class="absolute end-2.5 w-24 top-1/2 -translate-y-1/2 text-gray-900 dark:text-gray-400 hover:bg-gray-100 dark:bg-gray-800 dark:border-gray-600 dark:hover:bg-gray-700 rounded-lg py-2 px-2.5 inline-flex items-center justify-center bg-white border-gray-200 border">
Expand Down
2 changes: 1 addition & 1 deletion resources/js/Pages/Nodes/Partials/AgentStatus.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ defineProps([
</div>
</div>
<div v-else class="col-span-10">
<AgentInstall />
<AgentInstall :node="$props.node" />
</div>
</template>

Expand Down
6 changes: 3 additions & 3 deletions resources/js/Pages/Services/Create.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const form = useForm({
secretFiles: [],
placementNodeId: '',
volumes: [],
networkId: props.networks[0]?.id,
networkName: props.networks[0]?.docker_name,
internalDomain: '',
ports: [],
replicas: 1,
Expand Down Expand Up @@ -435,10 +435,10 @@ const createService = () => {
</template>

<template #content>
<FormField :error="form.errors.networkId">
<FormField :error="form.errors.networkName">
<template #label>Attach to Network</template>

<Select v-model="form.networkId">
<Select v-model="form.networkName">
<option v-for="network in $page.props.networks" :value="network.id">{{ network.name }}</option>
</Select>
</FormField>
Expand Down

0 comments on commit 0c87788

Please sign in to comment.