feat(dev): add example nginx connectivity commands
Add ping and firewall up/down helpers for example nginx dev VMs. Remove the v5 home ready banner and coolify version controls, and render Flux status as a compact summary.
This commit is contained in:
parent
1e038fecae
commit
5c23b9aaa5
5 changed files with 123 additions and 62 deletions
|
|
@ -25,7 +25,6 @@ public function __invoke(Request $request, FluxHealth $fluxHealth): Response
|
||||||
$currentTeam = $request->attributes->get('v5.currentTeam');
|
$currentTeam = $request->attributes->get('v5.currentTeam');
|
||||||
|
|
||||||
return Inertia::render('Home', [
|
return Inertia::render('Home', [
|
||||||
'status' => 'v5-ready',
|
|
||||||
'flux' => $fluxHealth->check(),
|
'flux' => $fluxHealth->check(),
|
||||||
'clusters' => $this->clusters($currentTeam),
|
'clusters' => $this->clusters($currentTeam),
|
||||||
'cooldServers' => $this->cooldServers($currentTeam),
|
'cooldServers' => $this->cooldServers($currentTeam),
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
import { Head } from '@inertiajs/react';
|
import { Head } from '@inertiajs/react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
|
||||||
export default function Home({ status, currentTeam, teams, flux, clusters, cooldServers, privateKeys }) {
|
export default function Home({ currentTeam, teams, flux, clusters, cooldServers, privateKeys }) {
|
||||||
const firstPrivateKey = privateKeys[0]?.uuid || '';
|
const firstPrivateKey = privateKeys[0]?.uuid || '';
|
||||||
const [coolify, setCoolify] = useState(null);
|
|
||||||
const [checkingCoolify, setCheckingCoolify] = useState(false);
|
|
||||||
const [bootstrapResult, setBootstrapResult] = useState(null);
|
const [bootstrapResult, setBootstrapResult] = useState(null);
|
||||||
const [bootstrapping, setBootstrapping] = useState(false);
|
const [bootstrapping, setBootstrapping] = useState(false);
|
||||||
const [bootstrapForm, setBootstrapForm] = useState({
|
const [bootstrapForm, setBootstrapForm] = useState({
|
||||||
|
|
@ -29,30 +27,6 @@ export default function Home({ status, currentTeam, teams, flux, clusters, coold
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkCoolifyCliVersion() {
|
|
||||||
setCheckingCoolify(true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch('/v5/coolify/version', {
|
|
||||||
headers: {
|
|
||||||
Accept: 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
setCoolify(await response.json());
|
|
||||||
} catch (error) {
|
|
||||||
setCoolify({
|
|
||||||
available: false,
|
|
||||||
label: 'Unavailable',
|
|
||||||
version: null,
|
|
||||||
message: 'Could not check the installed coolify version.',
|
|
||||||
binary: null,
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
setCheckingCoolify(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function bootstrapCoolifyMesh(event) {
|
async function bootstrapCoolifyMesh(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
setBootstrapping(true);
|
setBootstrapping(true);
|
||||||
|
|
@ -101,25 +75,12 @@ export default function Home({ status, currentTeam, teams, flux, clusters, coold
|
||||||
<Head title="V5" />
|
<Head title="V5" />
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<p>{status}</p>
|
|
||||||
|
|
||||||
<h1>Coolify v5</h1>
|
<h1>Coolify v5</h1>
|
||||||
|
|
||||||
<p>
|
<section aria-label="Flux status">
|
||||||
This page is served from Laravel through Inertia and React, with routes,
|
|
||||||
assets, and future v5 tables isolated from the current v4 Livewire app.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<section aria-labelledby="flux-status-heading">
|
|
||||||
<h2 id="flux-status-heading">Flux status</h2>
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<strong>{flux.label}</strong>
|
<strong>Flux:</strong> {flux.label} — {flux.socket ? flux.socket : flux.message}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>{flux.message}</p>
|
|
||||||
|
|
||||||
{flux.socket ? <p>Socket: {flux.socket}</p> : null}
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section aria-labelledby="clusters-heading">
|
<section aria-labelledby="clusters-heading">
|
||||||
|
|
@ -173,21 +134,6 @@ export default function Home({ status, currentTeam, teams, flux, clusters, coold
|
||||||
<section aria-labelledby="coolify-heading">
|
<section aria-labelledby="coolify-heading">
|
||||||
<h2 id="coolify-heading">coolify</h2>
|
<h2 id="coolify-heading">coolify</h2>
|
||||||
|
|
||||||
<button type="button" onClick={checkCoolifyCliVersion} disabled={checkingCoolify}>
|
|
||||||
{checkingCoolify ? 'Checking coolify...' : 'Check coolify version'}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{coolify ? (
|
|
||||||
<div>
|
|
||||||
<p>
|
|
||||||
<strong>{coolify.label}</strong>
|
|
||||||
</p>
|
|
||||||
{coolify.version ? <p>Version: {coolify.version}</p> : null}
|
|
||||||
<p>{coolify.message}</p>
|
|
||||||
{coolify.binary ? <p>Binary: {coolify.binary}</p> : null}
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
<form onSubmit={bootstrapCoolifyMesh}>
|
<form onSubmit={bootstrapCoolifyMesh}>
|
||||||
<h3>Bootstrap server</h3>
|
<h3>Bootstrap server</h3>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -816,14 +816,67 @@ sudo podman exec coolify-example-nginx nslookup coolify-example-nginx-2.default.
|
||||||
SH
|
SH
|
||||||
}
|
}
|
||||||
|
|
||||||
|
example_nginx_require_pair() {
|
||||||
|
if [ "$(coold_vm_count)" = "1" ]; then
|
||||||
|
echo "ERROR: example-nginx ping/firewall commands require COOLIFY_COOLD_VM_COUNT=2." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
example_nginx_container_ip() {
|
||||||
|
local index="$1"
|
||||||
|
local name
|
||||||
|
name="$(example_nginx_name "$index")"
|
||||||
|
|
||||||
|
COOLIFY_COOLD_LIMA_INSTANCE="$(coold_vm_instance "$index")" scripts/coold-vm.sh shell <<SH
|
||||||
|
set -e
|
||||||
|
sudo podman inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ${name}
|
||||||
|
SH
|
||||||
|
}
|
||||||
|
|
||||||
|
example_nginx_ping() {
|
||||||
|
example_nginx_require_pair
|
||||||
|
|
||||||
|
COOLIFY_COOLD_LIMA_INSTANCE="$(coold_vm_instance 1)" scripts/coold-vm.sh shell <<'SH'
|
||||||
|
set -e
|
||||||
|
sudo podman exec coolify-example-nginx wget -qO- --timeout=3 http://coolify-example-nginx-2.default.coolify.internal/ >/dev/null
|
||||||
|
echo 'ok: coolify-example-nginx can reach coolify-example-nginx-2 on tcp/80'
|
||||||
|
SH
|
||||||
|
}
|
||||||
|
|
||||||
|
example_nginx_firewall_up() {
|
||||||
|
local src
|
||||||
|
local dst
|
||||||
|
example_nginx_require_pair
|
||||||
|
|
||||||
|
src="$(example_nginx_container_ip 1)"
|
||||||
|
dst="$(example_nginx_container_ip 2)"
|
||||||
|
|
||||||
|
scripts/dev.sh firewall allow "$src" "$dst" tcp 80
|
||||||
|
}
|
||||||
|
|
||||||
|
example_nginx_firewall_down() {
|
||||||
|
local src
|
||||||
|
local dst
|
||||||
|
example_nginx_require_pair
|
||||||
|
|
||||||
|
src="$(example_nginx_container_ip 1)"
|
||||||
|
dst="$(example_nginx_container_ip 2)"
|
||||||
|
|
||||||
|
scripts/dev.sh firewall revoke "$src" "$dst" tcp 80
|
||||||
|
}
|
||||||
|
|
||||||
example_nginx_help() {
|
example_nginx_help() {
|
||||||
cat <<'USAGE'
|
cat <<'USAGE'
|
||||||
Usage: scripts/dev.sh example-nginx <command>
|
Usage: scripts/dev.sh example-nginx <command>
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
up Start one nginx container on each coold VM with coold DNS configured
|
up Start one nginx container on each coold VM with coold DNS configured
|
||||||
down Remove the example nginx containers
|
down Remove the example nginx containers
|
||||||
check-dns Verify host 1 nginx can resolve host 2 nginx through coold DNS
|
check-dns Verify host 1 nginx can resolve host 2 nginx through coold DNS
|
||||||
|
ping Verify host 1 nginx can reach host 2 nginx on tcp/80
|
||||||
|
firewall up Allow host 1 nginx to reach host 2 nginx through the coolify CLI
|
||||||
|
firewall down Revoke the example nginx tcp/80 allow rule through the coolify CLI
|
||||||
USAGE
|
USAGE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -843,6 +896,24 @@ example_nginx() {
|
||||||
check-dns)
|
check-dns)
|
||||||
example_nginx_check_dns
|
example_nginx_check_dns
|
||||||
;;
|
;;
|
||||||
|
ping)
|
||||||
|
example_nginx_ping
|
||||||
|
;;
|
||||||
|
firewall)
|
||||||
|
case "${1:-help}" in
|
||||||
|
up)
|
||||||
|
example_nginx_firewall_up
|
||||||
|
;;
|
||||||
|
down)
|
||||||
|
example_nginx_firewall_down
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "unknown example-nginx firewall command: ${1:-help}" >&2
|
||||||
|
echo "Run: scripts/dev.sh example-nginx help" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
-h|--help|help)
|
-h|--help|help)
|
||||||
example_nginx_help
|
example_nginx_help
|
||||||
;;
|
;;
|
||||||
|
|
|
||||||
23
tests/Feature/DevScriptExampleNginxTest.php
Normal file
23
tests/Feature/DevScriptExampleNginxTest.php
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
|
it('documents example nginx connectivity and firewall commands', function () {
|
||||||
|
$process = new Process(['bash', base_path('scripts/dev.sh'), 'example-nginx', 'help'], base_path());
|
||||||
|
|
||||||
|
$process->run();
|
||||||
|
|
||||||
|
expect($process->isSuccessful())->toBeTrue()
|
||||||
|
->and($process->getOutput())->toContain('ping')
|
||||||
|
->and($process->getOutput())->toContain('firewall up')
|
||||||
|
->and($process->getOutput())->toContain('firewall down')
|
||||||
|
->and($process->getOutput())->not->toContain('firewall-up')
|
||||||
|
->and($process->getOutput())->not->toContain('firewall-down');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses the coolify firewall wrapper for example nginx firewall changes', function () {
|
||||||
|
$script = file_get_contents(base_path('scripts/dev.sh'));
|
||||||
|
|
||||||
|
expect($script)->toContain('scripts/dev.sh firewall allow "$src" "$dst" tcp 80')
|
||||||
|
->and($script)->toContain('scripts/dev.sh firewall revoke "$src" "$dst" tcp 80');
|
||||||
|
});
|
||||||
|
|
@ -184,7 +184,8 @@
|
||||||
->assertSuccessful()
|
->assertSuccessful()
|
||||||
->assertSee('v5-app', false)
|
->assertSee('v5-app', false)
|
||||||
->assertSee('Home', false)
|
->assertSee('Home', false)
|
||||||
->assertSee('v5-ready', false)
|
->assertDontSee('v5-ready', false)
|
||||||
|
->assertDontSee('This page is served from Laravel through Inertia and React')
|
||||||
->assertSee('Running')
|
->assertSee('Running')
|
||||||
->assertSee('Flux is running.')
|
->assertSee('Flux is running.')
|
||||||
->assertSee('"clusters":[]', false)
|
->assertSee('"clusters":[]', false)
|
||||||
|
|
@ -294,6 +295,27 @@
|
||||||
->assertSee('Flux socket was not found.');
|
->assertSee('Flux socket was not found.');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not include coolify version controls on the v5 home page', function () {
|
||||||
|
$homePage = file_get_contents(resource_path('js/v5/Pages/Home.jsx'));
|
||||||
|
|
||||||
|
expect($homePage)
|
||||||
|
->not->toContain('Check coolify version')
|
||||||
|
->not->toContain('/v5/coolify/version')
|
||||||
|
->not->toContain('Installed version:');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders flux status as a compact summary', function () {
|
||||||
|
$homePage = file_get_contents(resource_path('js/v5/Pages/Home.jsx'));
|
||||||
|
|
||||||
|
expect($homePage)
|
||||||
|
->toContain('<strong>Flux:</strong>')
|
||||||
|
->toContain('{flux.label}')
|
||||||
|
->toContain('{flux.socket ? flux.socket : flux.message}')
|
||||||
|
->not->toContain('<h2 id="flux-status-heading">Flux status</h2>')
|
||||||
|
->not->toContain('<p>{flux.message}</p>')
|
||||||
|
->not->toContain('Socket: {flux.socket}');
|
||||||
|
});
|
||||||
|
|
||||||
it('checks the installed coolify version', function () {
|
it('checks the installed coolify version', function () {
|
||||||
createSharedUserAndTeamTables();
|
createSharedUserAndTeamTables();
|
||||||
[$user, $team] = createV5UserWithTeam();
|
[$user, $team] = createV5UserWithTeam();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue