Skip to content

Commit 0037a61

Browse files
committed
feat: #12 watch after the new agent releases
1 parent 24450eb commit 0037a61

27 files changed

+454
-9
lines changed

.env.example

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
APP_NAME=Laravel
1+
APP_NAME=Ptah.sh
22
APP_ENV=local
33
APP_KEY=
44
APP_DEBUG=true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace App\Events\NodeTasks\ConfirmAgentUpgrade;
4+
5+
use App\Events\NodeTasks\BaseTaskEvent;
6+
7+
class ConfirmAgentUpgradeCompleted extends BaseTaskEvent
8+
{
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace App\Events\NodeTasks\ConfirmAgentUpgrade;
4+
5+
use App\Events\NodeTasks\BaseTaskEvent;
6+
7+
class ConfirmAgentUpgradeFailed extends BaseTaskEvent
8+
{
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace App\Events\NodeTasks\DownloadAgentUpgrade;
4+
5+
use App\Events\NodeTasks\BaseTaskEvent;
6+
7+
class DownloadAgentUpgradeCompleted extends BaseTaskEvent
8+
{
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace App\Events\NodeTasks\DownloadAgentUpgrade;
4+
5+
use App\Events\NodeTasks\BaseTaskEvent;
6+
7+
class DownloadAgentUpgradeFailed extends BaseTaskEvent
8+
{
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace App\Events\NodeTasks\UpdateAgentSymlink;
4+
5+
use App\Events\NodeTasks\BaseTaskEvent;
6+
7+
class UpdateAgentSymlinkCompleted extends BaseTaskEvent
8+
{
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace App\Events\NodeTasks\UpdateAgentSymlink;
4+
5+
use App\Events\NodeTasks\BaseTaskEvent;
6+
7+
class UpdateAgentSymlinkFailed extends BaseTaskEvent
8+
{
9+
}

app/Http/Controllers/NodeController.php

+26-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44

55
use App\Http\Requests\StoreNodeRequest;
66
use App\Http\Requests\UpdateNodeRequest;
7+
use App\Models\AgentRelease;
78
use App\Models\Node;
89
use App\Models\NodeTaskGroupType;
10+
use Illuminate\Http\Request;
11+
use Illuminate\Support\Facades\DB;
912
use Inertia\Inertia;
1013

1114
class NodeController extends Controller
@@ -48,7 +51,16 @@ public function show(Node $node)
4851
$initTaskGroup = null;
4952
}
5053

51-
return Inertia::render('Nodes/Show', ['node' => $node, 'initTaskGroup' => $initTaskGroup]);
54+
$lastAgentVersion = AgentRelease::latest()->sole()->tag_name;
55+
56+
$taskGroup = $node->actualTaskGroup(NodeTaskGroupType::SelfUpgrade);
57+
58+
return Inertia::render('Nodes/Show', [
59+
'node' => $node,
60+
'initTaskGroup' => $initTaskGroup,
61+
'lastAgentVersion' => $lastAgentVersion,
62+
'agentUpgradeTaskGroup' => $taskGroup?->is_completed ? null : $taskGroup,
63+
]);
5264
}
5365

5466
/**
@@ -74,4 +86,17 @@ public function destroy(Node $node)
7486
{
7587
//
7688
}
89+
90+
public function upgradeAgent(Node $node, Request $request)
91+
{
92+
$req = $request->validate([
93+
'targetVersion' => ['required', 'exists:agent_releases,tag_name'],
94+
]);
95+
96+
DB::transaction(function () use ($node, $req) {
97+
$node->upgradeAgent($req['targetVersion']);
98+
});
99+
100+
return to_route('nodes.show', ['node' => $node->id]);
101+
}
77102
}

app/Jobs/CheckAgentUpdates.php

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
namespace App\Jobs;
4+
5+
use App\Models\AgentRelease;
6+
use Illuminate\Bus\Queueable;
7+
use Illuminate\Contracts\Queue\ShouldQueue;
8+
use Illuminate\Foundation\Bus\Dispatchable;
9+
use Illuminate\Queue\InteractsWithQueue;
10+
use Illuminate\Queue\SerializesModels;
11+
use Illuminate\Support\Facades\Http;
12+
13+
class CheckAgentUpdates implements ShouldQueue
14+
{
15+
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
16+
17+
/**
18+
* Create a new job instance.
19+
*/
20+
public function __construct()
21+
{
22+
}
23+
24+
/**
25+
* Execute the job.
26+
*/
27+
public function handle(): void
28+
{
29+
$json = Http::get("https://api.github.com/repos/ptah-sh/ptah-agent/releases/latest")->json();
30+
31+
foreach ($json['assets'] as $asset) {
32+
preg_match('/^ptah-agent-(?<os>.+)-(?<arch>.+).bin$/', $asset['name'], $matches);
33+
if (empty($matches)) {
34+
continue;
35+
}
36+
37+
$attrs = [
38+
'tag_name' => $json['tag_name'],
39+
'download_url' => $asset['browser_download_url'],
40+
'os' => $matches['os'],
41+
'arch' => $matches['arch'],
42+
];
43+
44+
AgentRelease::firstOrCreate($attrs, $attrs);
45+
}
46+
}
47+
}

app/Models/AgentRelease.php

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace App\Models;
4+
5+
use Illuminate\Database\Eloquent\Factories\HasFactory;
6+
use Illuminate\Database\Eloquent\Model;
7+
8+
class AgentRelease extends Model
9+
{
10+
use HasFactory;
11+
12+
protected $fillable = [
13+
'tag_name',
14+
'download_url',
15+
'os',
16+
'arch',
17+
];
18+
}

app/Models/Node.php

+44
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,48 @@ public function actualTaskGroup($type): ?NodeTaskGroup
5959

6060
return $base->orderByDesc('id')->take(1)->get()[0] ?? null;
6161
}
62+
63+
public function upgradeAgent($targetVersion): void
64+
{
65+
$release = AgentRelease::where('tag_name', $targetVersion)->sole();
66+
67+
$taskGroup = NodeTaskGroup::create([
68+
'swarm_id' => $this->swarm_id,
69+
'node_id' => $this->id,
70+
'type' => NodeTaskGroupType::SelfUpgrade,
71+
'invoker_id' => auth()->user()->id,
72+
]);
73+
74+
$taskGroup->tasks()->createMany([
75+
[
76+
'type' => NodeTaskType::DownloadAgentUpgrade,
77+
'meta' => [
78+
'targetVersion' => $targetVersion,
79+
'downloadUrl' => $release->download_url,
80+
],
81+
'payload' => [
82+
'TargetVersion' => $targetVersion,
83+
'DownloadUrl' => $release->download_url,
84+
]
85+
],
86+
[
87+
'type' => NodeTaskType::UpdateAgentSymlink,
88+
'meta' => [
89+
'targetVersion' => $targetVersion,
90+
],
91+
'payload' => [
92+
'TargetVersion' => $targetVersion,
93+
]
94+
],
95+
[
96+
'type' => NodeTaskType::ConfirmAgentUpgrade,
97+
'meta' => [
98+
'targetVersion' => $targetVersion,
99+
],
100+
'payload' => [
101+
'TargetVersion' => $targetVersion,
102+
]
103+
]
104+
]);
105+
}
62106
}

app/Models/NodeTaskGroupType.php

+1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ enum NodeTaskGroupType: int
88
case CreateService = 1;
99
case UpdateService = 2;
1010
case DeleteService = 3;
11+
case SelfUpgrade = 4;
1112
}

app/Models/NodeTaskType.php

+27
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace App\Models;
44

5+
use App\Events\NodeTasks\ConfirmAgentUpgrade\ConfirmAgentUpgradeCompleted;
6+
use App\Events\NodeTasks\ConfirmAgentUpgrade\ConfirmAgentUpgradeFailed;
57
use App\Events\NodeTasks\CreateConfig\CreateConfigCompleted;
68
use App\Events\NodeTasks\CreateConfig\CreateConfigFailed;
79
use App\Events\NodeTasks\CreateNetwork\CreateNetworkCompleted;
@@ -12,14 +14,20 @@
1214
use App\Events\NodeTasks\CreateService\CreateServiceFailed;
1315
use App\Events\NodeTasks\DeleteService\DeleteServiceCompleted;
1416
use App\Events\NodeTasks\DeleteService\DeleteServiceFailed;
17+
use App\Events\NodeTasks\DownloadAgentUpgrade\DownloadAgentUpgradeCompleted;
18+
use App\Events\NodeTasks\DownloadAgentUpgrade\DownloadAgentUpgradeFailed;
1519
use App\Events\NodeTasks\InitSwarm\InitSwarmCompleted;
1620
use App\Events\NodeTasks\InitSwarm\InitSwarmFailed;
1721
use App\Events\NodeTasks\RebuildCaddyConfig\ApplyCaddyConfigCompleted;
1822
use App\Events\NodeTasks\RebuildCaddyConfig\ApplyCaddyConfigFailed;
23+
use App\Events\NodeTasks\UpdateAgentSymlink\UpdateAgentSymlinkCompleted;
24+
use App\Events\NodeTasks\UpdateAgentSymlink\UpdateAgentSymlinkFailed;
1925
use App\Events\NodeTasks\UpdateNode\UpdateCurrentNodeCompleted;
2026
use App\Events\NodeTasks\UpdateNode\UpdateCurrentNodeFailed;
2127
use App\Events\NodeTasks\UpdateService\UpdateServiceCompleted;
2228
use App\Events\NodeTasks\UpdateService\UpdateServiceFailed;
29+
use App\Models\NodeTasks\ConfirmAgentUpgrade\ConfirmAgentUpgradeMeta;
30+
use App\Models\NodeTasks\ConfirmAgentUpgrade\ConfirmAgentUpgradeResult;
2331
use App\Models\NodeTasks\CreateConfig\CreateConfigMeta;
2432
use App\Models\NodeTasks\CreateConfig\CreateConfigResult;
2533
use App\Models\NodeTasks\CreateNetwork\CreateNetworkMeta;
@@ -30,10 +38,14 @@
3038
use App\Models\NodeTasks\CreateService\CreateServiceResult;
3139
use App\Models\NodeTasks\DeleteService\DeleteServiceMeta;
3240
use App\Models\NodeTasks\DeleteService\DeleteServiceResult;
41+
use App\Models\NodeTasks\DownloadAgentUpgrade\DownloadAgentUpgradeMeta;
42+
use App\Models\NodeTasks\DownloadAgentUpgrade\DownloadAgentUpgradeResult;
3343
use App\Models\NodeTasks\InitSwarm\InitSwarmMeta;
3444
use App\Models\NodeTasks\InitSwarm\InitSwarmResult;
3545
use App\Models\NodeTasks\ApplyCaddyConfig\ApplyCaddyConfigMeta;
3646
use App\Models\NodeTasks\ApplyCaddyConfig\ApplyCaddyConfigResult;
47+
use App\Models\NodeTasks\UpdateAgentSymlink\UpdateAgentSymlinkMeta;
48+
use App\Models\NodeTasks\UpdateAgentSymlink\UpdateAgentSymlinkResult;
3749
use App\Models\NodeTasks\UpdateCurrentNode\UpdateCurrentNodeMeta;
3850
use App\Models\NodeTasks\UpdateCurrentNode\UpdateCurrentNodeResult;
3951
use App\Models\NodeTasks\UpdateService\UpdateServiceMeta;
@@ -51,6 +63,9 @@ enum NodeTaskType: int
5163
case UpdateService = 6;
5264
case UpdateCurrentNode = 7;
5365
case DeleteService = 8;
66+
case DownloadAgentUpgrade = 9;
67+
case UpdateAgentSymlink = 10;
68+
case ConfirmAgentUpgrade = 11;
5469

5570
public function meta(): string
5671
{
@@ -64,6 +79,9 @@ public function meta(): string
6479
self::UpdateService => UpdateServiceMeta::class,
6580
self::UpdateCurrentNode => UpdateCurrentNodeMeta::class,
6681
self::DeleteService => DeleteServiceMeta::class,
82+
self::DownloadAgentUpgrade => DownloadAgentUpgradeMeta::class,
83+
self::UpdateAgentSymlink => UpdateAgentSymlinkMeta::class,
84+
self::ConfirmAgentUpgrade => ConfirmAgentUpgradeMeta::class,
6785
};
6886
}
6987

@@ -79,6 +97,9 @@ public function result(): string
7997
self::UpdateService => UpdateServiceResult::class,
8098
self::UpdateCurrentNode => UpdateCurrentNodeResult::class,
8199
self::DeleteService => DeleteServiceResult::class,
100+
self::DownloadAgentUpgrade => DownloadAgentUpgradeResult::class,
101+
self::UpdateAgentSymlink => UpdateAgentSymlinkResult::class,
102+
self::ConfirmAgentUpgrade => ConfirmAgentUpgradeResult::class,
82103
};
83104
}
84105

@@ -94,6 +115,9 @@ public function completed(): string
94115
self::UpdateService => UpdateServiceCompleted::class,
95116
self::UpdateCurrentNode => UpdateCurrentNodeCompleted::class,
96117
self::DeleteService => DeleteServiceCompleted::class,
118+
self::DownloadAgentUpgrade => DownloadAgentUpgradeCompleted::class,
119+
self::UpdateAgentSymlink => UpdateAgentSymlinkCompleted::class,
120+
self::ConfirmAgentUpgrade => ConfirmAgentUpgradeCompleted::class,
97121
};
98122
}
99123

@@ -109,6 +133,9 @@ public function failed(): string
109133
self::UpdateService => UpdateServiceFailed::class,
110134
self::UpdateCurrentNode => UpdateCurrentNodeFailed::class,
111135
self::DeleteService => DeleteServiceFailed::class,
136+
self::DownloadAgentUpgrade => DownloadAgentUpgradeFailed::class,
137+
self::UpdateAgentSymlink => UpdateAgentSymlinkFailed::class,
138+
self::ConfirmAgentUpgrade => ConfirmAgentUpgradeFailed::class,
112139
};
113140
}
114141
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace App\Models\NodeTasks\ConfirmAgentUpgrade;
4+
5+
use App\Models\NodeTasks\AbstractTaskMeta;
6+
7+
class ConfirmAgentUpgradeMeta extends AbstractTaskMeta
8+
{
9+
public function __construct(
10+
public string $targetVersion
11+
)
12+
{
13+
//
14+
}
15+
16+
public function formattedHtml(): string
17+
{
18+
return "Confirm agent upgrade to <code>{$this->targetVersion}</code>";
19+
}
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace App\Models\NodeTasks\ConfirmAgentUpgrade;
4+
5+
use App\Models\NodeTasks\AbstractTaskResult;
6+
7+
class ConfirmAgentUpgradeResult extends AbstractTaskResult
8+
{
9+
public function __construct(
10+
)
11+
{
12+
//
13+
}
14+
15+
public function formattedHtml(): string
16+
{
17+
return "Success.";
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace App\Models\NodeTasks\DownloadAgentUpgrade;
4+
5+
use App\Models\NodeTasks\AbstractTaskMeta;
6+
7+
class DownloadAgentUpgradeMeta extends AbstractTaskMeta
8+
{
9+
public function __construct(
10+
public string $targetVersion,
11+
public string $downloadUrl
12+
)
13+
{
14+
//
15+
}
16+
17+
public function formattedHtml(): string
18+
{
19+
return "Download agent upgrade to <code>{$this->targetVersion}</code>";
20+
}
21+
}

0 commit comments

Comments
 (0)