fix: toast, rde, webhooks
This commit is contained in:
parent
fa9738a2e0
commit
9dfbbe58ff
@ -34,7 +34,6 @@ export async function migrateServicesToNewTemplate() {
|
|||||||
if (!service.type) {
|
if (!service.type) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
console.log(service.type)
|
|
||||||
let template = templates.find(t => fixType(t.type) === fixType(service.type));
|
let template = templates.find(t => fixType(t.type) === fixType(service.type));
|
||||||
if (template) {
|
if (template) {
|
||||||
template = JSON.parse(JSON.stringify(template).replaceAll('$$id', service.id))
|
template = JSON.parse(JSON.stringify(template).replaceAll('$$id', service.id))
|
||||||
|
@ -505,56 +505,59 @@ export async function createRemoteEngineConfiguration(id: string) {
|
|||||||
const localPort = await getFreeSSHLocalPort(id);
|
const localPort = await getFreeSSHLocalPort(id);
|
||||||
const {
|
const {
|
||||||
sshKey: { privateKey },
|
sshKey: { privateKey },
|
||||||
|
network,
|
||||||
remoteIpAddress,
|
remoteIpAddress,
|
||||||
remotePort,
|
remotePort,
|
||||||
remoteUser
|
remoteUser
|
||||||
} = await prisma.destinationDocker.findFirst({ where: { id }, include: { sshKey: true } });
|
} = await prisma.destinationDocker.findFirst({ where: { id }, include: { sshKey: true } });
|
||||||
await fs.writeFile(sshKeyFile, decrypt(privateKey) + '\n', { encoding: 'utf8', mode: 400 });
|
await fs.writeFile(sshKeyFile, decrypt(privateKey) + '\n', { encoding: 'utf8', mode: 400 });
|
||||||
// Needed for remote docker compose
|
// Needed for remote docker compose
|
||||||
const { stdout: numberOfSSHAgentsRunning } = await asyncExecShell(
|
// const { stdout: numberOfSSHAgentsRunning } = await asyncExecShell(
|
||||||
`ps ax | grep [s]sh-agent | grep coolify-ssh-agent.pid | grep -v grep | wc -l`
|
// `ps ax | grep [s]sh-agent | grep coolify-ssh-agent.pid | grep -v grep | wc -l`
|
||||||
);
|
// );
|
||||||
if (numberOfSSHAgentsRunning !== '' && Number(numberOfSSHAgentsRunning.trim()) == 0) {
|
// if (numberOfSSHAgentsRunning !== '' && Number(numberOfSSHAgentsRunning.trim()) == 0) {
|
||||||
try {
|
// try {
|
||||||
await fs.stat(`/tmp/coolify-ssh-agent.pid`);
|
// await fs.stat(`/tmp/coolify-ssh-agent.pid`);
|
||||||
await fs.rm(`/tmp/coolify-ssh-agent.pid`);
|
// await fs.rm(`/tmp/coolify-ssh-agent.pid`);
|
||||||
} catch (error) { }
|
// } catch (error) { }
|
||||||
await asyncExecShell(`eval $(ssh-agent -sa /tmp/coolify-ssh-agent.pid)`);
|
// await asyncExecShell(`eval $(ssh-agent -sa /tmp/coolify-ssh-agent.pid)`);
|
||||||
}
|
// }
|
||||||
await asyncExecShell(`SSH_AUTH_SOCK=/tmp/coolify-ssh-agent.pid ssh-add -q ${sshKeyFile}`);
|
// await asyncExecShell(`SSH_AUTH_SOCK=/tmp/coolify-ssh-agent.pid ssh-add -q ${sshKeyFile}`);
|
||||||
|
|
||||||
const { stdout: numberOfSSHTunnelsRunning } = await asyncExecShell(
|
// const { stdout: numberOfSSHTunnelsRunning } = await asyncExecShell(
|
||||||
`ps ax | grep 'ssh -F /dev/null -o StrictHostKeyChecking no -fNL ${localPort}:localhost:${remotePort}' | grep -v grep | wc -l`
|
// `ps ax | grep 'ssh -F /dev/null -o StrictHostKeyChecking no -fNL ${localPort}:localhost:${remotePort}' | grep -v grep | wc -l`
|
||||||
);
|
// );
|
||||||
if (numberOfSSHTunnelsRunning !== '' && Number(numberOfSSHTunnelsRunning.trim()) == 0) {
|
// if (numberOfSSHTunnelsRunning !== '' && Number(numberOfSSHTunnelsRunning.trim()) == 0) {
|
||||||
try {
|
// try {
|
||||||
await asyncExecShell(
|
// await asyncExecShell(
|
||||||
`SSH_AUTH_SOCK=/tmp/coolify-ssh-agent.pid ssh -F /dev/null -o "StrictHostKeyChecking no" -fNL ${localPort}:localhost:${remotePort} ${remoteUser}@${remoteIpAddress}`
|
// `SSH_AUTH_SOCK=/tmp/coolify-ssh-agent.pid ssh -F /dev/null -o "StrictHostKeyChecking no" -fNL ${localPort}:localhost:${remotePort} ${remoteUser}@${remoteIpAddress}`
|
||||||
);
|
// );
|
||||||
} catch (error) { }
|
// } catch (error) { }
|
||||||
}
|
// }
|
||||||
const config = sshConfig.parse('');
|
const config = sshConfig.parse('');
|
||||||
const foundWildcard = config.find({ Host: '*' });
|
const Host = `${remoteIpAddress}-remote`
|
||||||
if (!foundWildcard) {
|
|
||||||
config.append({
|
await asyncExecShell(`ssh-keygen -R ${Host}`);
|
||||||
Host: '*',
|
await asyncExecShell(`ssh-keygen -R ${remoteIpAddress}`);
|
||||||
StrictHostKeyChecking: 'no',
|
await asyncExecShell(`ssh-keygen -R localhost:${localPort}`);
|
||||||
ControlMaster: 'auto',
|
|
||||||
ControlPath: `${homedir}/.ssh/coolify-%r@%h:%p`,
|
const found = config.find({ Host });
|
||||||
ControlPersist: '10m'
|
const foundIp = config.find({ Host: remoteIpAddress });
|
||||||
})
|
|
||||||
}
|
if (found) config.remove({ Host })
|
||||||
const found = config.find({ Host: remoteIpAddress });
|
if (foundIp) config.remove({ Host: remoteIpAddress })
|
||||||
if (!found) {
|
|
||||||
config.append({
|
config.append({
|
||||||
Host: remoteIpAddress,
|
Host,
|
||||||
Hostname: 'localhost',
|
Hostname: remoteIpAddress,
|
||||||
Port: localPort.toString(),
|
Port: remotePort.toString(),
|
||||||
User: remoteUser,
|
User: remoteUser,
|
||||||
IdentityFile: sshKeyFile,
|
StrictHostKeyChecking: 'no',
|
||||||
StrictHostKeyChecking: 'no'
|
IdentityFile: sshKeyFile,
|
||||||
});
|
ControlMaster: 'auto',
|
||||||
}
|
ControlPath: `${homedir}/.ssh/coolify-${remoteIpAddress}-%r@%h:%p`,
|
||||||
|
ControlPersist: '10m'
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fs.stat(`${homedir}/.ssh/`);
|
await fs.stat(`${homedir}/.ssh/`);
|
||||||
@ -565,27 +568,23 @@ export async function createRemoteEngineConfiguration(id: string) {
|
|||||||
}
|
}
|
||||||
export async function executeSSHCmd({ dockerId, command }) {
|
export async function executeSSHCmd({ dockerId, command }) {
|
||||||
const { execaCommand } = await import('execa')
|
const { execaCommand } = await import('execa')
|
||||||
let { remoteEngine, remoteIpAddress, engine, remoteUser } = await prisma.destinationDocker.findUnique({ where: { id: dockerId } })
|
let { remoteEngine, remoteIpAddress } = await prisma.destinationDocker.findUnique({ where: { id: dockerId } })
|
||||||
if (remoteEngine) {
|
if (remoteEngine) {
|
||||||
await createRemoteEngineConfiguration(dockerId)
|
await createRemoteEngineConfiguration(dockerId)
|
||||||
engine = `ssh://${remoteIpAddress}`
|
|
||||||
} else {
|
|
||||||
engine = 'unix:///var/run/docker.sock'
|
|
||||||
}
|
}
|
||||||
if (process.env.CODESANDBOX_HOST) {
|
if (process.env.CODESANDBOX_HOST) {
|
||||||
if (command.startsWith('docker compose')) {
|
if (command.startsWith('docker compose')) {
|
||||||
command = command.replace(/docker compose/gi, 'docker-compose')
|
command = command.replace(/docker compose/gi, 'docker-compose')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
command = `ssh ${remoteIpAddress} ${command}`
|
return await execaCommand(`ssh ${remoteIpAddress}-remote ${command}`)
|
||||||
return await execaCommand(command)
|
|
||||||
}
|
}
|
||||||
export async function executeDockerCmd({ debug, buildId, applicationId, dockerId, command }: { debug?: boolean, buildId?: string, applicationId?: string, dockerId: string, command: string }): Promise<any> {
|
export async function executeDockerCmd({ debug, buildId, applicationId, dockerId, command }: { debug?: boolean, buildId?: string, applicationId?: string, dockerId: string, command: string }): Promise<any> {
|
||||||
const { execaCommand } = await import('execa')
|
const { execaCommand } = await import('execa')
|
||||||
let { remoteEngine, remoteIpAddress, engine, remoteUser } = await prisma.destinationDocker.findUnique({ where: { id: dockerId } })
|
let { remoteEngine, remoteIpAddress, engine } = await prisma.destinationDocker.findUnique({ where: { id: dockerId } })
|
||||||
if (remoteEngine) {
|
if (remoteEngine) {
|
||||||
await createRemoteEngineConfiguration(dockerId);
|
await createRemoteEngineConfiguration(dockerId);
|
||||||
engine = `ssh://${remoteIpAddress}`;
|
engine = `ssh://${remoteIpAddress}-remote`;
|
||||||
} else {
|
} else {
|
||||||
engine = 'unix:///var/run/docker.sock';
|
engine = 'unix:///var/run/docker.sock';
|
||||||
}
|
}
|
||||||
|
@ -204,8 +204,8 @@ export async function assignSSHKey(request: FastifyRequest) {
|
|||||||
}
|
}
|
||||||
export async function verifyRemoteDockerEngineFn(id: string) {
|
export async function verifyRemoteDockerEngineFn(id: string) {
|
||||||
await createRemoteEngineConfiguration(id);
|
await createRemoteEngineConfiguration(id);
|
||||||
const { remoteIpAddress, remoteUser, network, isCoolifyProxyUsed } = await prisma.destinationDocker.findFirst({ where: { id } })
|
const { remoteIpAddress, network, isCoolifyProxyUsed } = await prisma.destinationDocker.findFirst({ where: { id } })
|
||||||
const host = `ssh://${remoteUser}@${remoteIpAddress}`
|
const host = `ssh://${remoteIpAddress}-remote`
|
||||||
const { stdout } = await asyncExecShell(`DOCKER_HOST=${host} docker network ls --filter 'name=${network}' --no-trunc --format "{{json .}}"`);
|
const { stdout } = await asyncExecShell(`DOCKER_HOST=${host} docker network ls --filter 'name=${network}' --no-trunc --format "{{json .}}"`);
|
||||||
if (!stdout) {
|
if (!stdout) {
|
||||||
await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable ${network}`);
|
await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable ${network}`);
|
||||||
@ -215,8 +215,8 @@ export async function verifyRemoteDockerEngineFn(id: string) {
|
|||||||
await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable coolify-infra`);
|
await asyncExecShell(`DOCKER_HOST=${host} docker network create --attachable coolify-infra`);
|
||||||
}
|
}
|
||||||
if (isCoolifyProxyUsed) await startTraefikProxy(id);
|
if (isCoolifyProxyUsed) await startTraefikProxy(id);
|
||||||
const { stdout: daemonJson } = await executeSSHCmd({ dockerId: id, command: `cat /etc/docker/daemon.json` });
|
|
||||||
try {
|
try {
|
||||||
|
const { stdout: daemonJson } = await executeSSHCmd({ dockerId: id, command: `cat /etc/docker/daemon.json` });
|
||||||
let daemonJsonParsed = JSON.parse(daemonJson);
|
let daemonJsonParsed = JSON.parse(daemonJson);
|
||||||
let isUpdated = false;
|
let isUpdated = false;
|
||||||
if (!daemonJsonParsed['live-restore'] || daemonJsonParsed['live-restore'] !== true) {
|
if (!daemonJsonParsed['live-restore'] || daemonJsonParsed['live-restore'] !== true) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,13 @@
|
|||||||
import { FastifyPluginAsync } from 'fastify';
|
import { FastifyPluginAsync } from 'fastify';
|
||||||
import { OnlyId } from '../../../types';
|
import { OnlyId } from '../../../types';
|
||||||
import { remoteTraefikConfiguration, traefikConfiguration, traefikOtherConfiguration } from './handlers';
|
import { traefikConfiguration, traefikOtherConfiguration } from './handlers';
|
||||||
import { TraefikOtherConfiguration } from './types';
|
import { TraefikOtherConfiguration } from './types';
|
||||||
|
|
||||||
const root: FastifyPluginAsync = async (fastify): Promise<void> => {
|
const root: FastifyPluginAsync = async (fastify): Promise<void> => {
|
||||||
fastify.get('/main.json', async (request, reply) => traefikConfiguration(request, reply));
|
fastify.get<OnlyId>('/main.json', async (request, reply) => traefikConfiguration(request, false));
|
||||||
fastify.get<TraefikOtherConfiguration>('/other.json', async (request, reply) => traefikOtherConfiguration(request));
|
fastify.get<OnlyId>('/remote/:id', async (request) => traefikConfiguration(request, true));
|
||||||
|
|
||||||
fastify.get<OnlyId>('/remote/:id', async (request) => remoteTraefikConfiguration(request));
|
fastify.get<TraefikOtherConfiguration>('/other.json', async (request, reply) => traefikOtherConfiguration(request));
|
||||||
};
|
};
|
||||||
|
|
||||||
export default root;
|
export default root;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
export interface OnlyId {
|
export interface OnlyId {
|
||||||
Params: { id: string },
|
Params: { id?: string },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
export let type = 'info';
|
export let type = 'info';
|
||||||
function success() {
|
function success() {
|
||||||
if (type === 'success') {
|
if (type === 'success') {
|
||||||
return 'bg-coollabs';
|
return 'bg-dark lg:bg-primary';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
{#if $toasts.length > 0}
|
{#if $toasts.length > 0}
|
||||||
<section>
|
<section>
|
||||||
<article class="toast toast-top toast-center rounded-none min-w-[18rem]" role="alert">
|
<article class="toast toast-top toast-center rounded-none w-2/3 lg:w-[20rem]" role="alert">
|
||||||
{#each $toasts as toast (toast.id)}
|
{#each $toasts as toast (toast.id)}
|
||||||
<Toast
|
<Toast
|
||||||
type={toast.type}
|
type={toast.type}
|
||||||
|
@ -68,12 +68,6 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="w-full relative p-5 ">
|
<div class="w-full relative p-5 ">
|
||||||
{#if loading.usage}
|
|
||||||
<span class="indicator-item badge bg-yellow-500 badge-sm" />
|
|
||||||
{:else}
|
|
||||||
<span class="indicator-item badge bg-success badge-sm" />
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class="w-full flex flex-col lg:flex-row space-y-4 lg:space-y-0 space-x-4">
|
<div class="w-full flex flex-col lg:flex-row space-y-4 lg:space-y-0 space-x-4">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<h1 class="font-bold text-lg lg:text-xl truncate">
|
<h1 class="font-bold text-lg lg:text-xl truncate">
|
||||||
@ -99,6 +93,11 @@
|
|||||||
class="btn btn-sm">Cleanup Storage</button
|
class="btn btn-sm">Cleanup Storage</button
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if loading.usage}
|
||||||
|
<button id="streaming" class=" btn btn-sm bg-transparent border-none loading"
|
||||||
|
>Getting data...</button
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex lg:flex-row flex-col gap-4">
|
<div class="flex lg:flex-row flex-col gap-4">
|
||||||
<div class="flex lg:flex-row flex-col space-x-0 lg:space-x-2 space-y-2 lg:space-y-0" />
|
<div class="flex lg:flex-row flex-col space-x-0 lg:space-x-2 space-y-2 lg:space-y-0" />
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
|
|
||||||
let statusInterval: any;
|
let statusInterval: any;
|
||||||
let forceDelete = false;
|
let forceDelete = false;
|
||||||
|
let stopping = false;
|
||||||
const { id } = $page.params;
|
const { id } = $page.params;
|
||||||
$isDeploymentEnabled = checkIfDeploymentEnabledApplications($appSession.isAdmin, application);
|
$isDeploymentEnabled = checkIfDeploymentEnabledApplications($appSession.isAdmin, application);
|
||||||
|
|
||||||
@ -138,17 +138,17 @@
|
|||||||
}
|
}
|
||||||
async function stopApplication() {
|
async function stopApplication() {
|
||||||
try {
|
try {
|
||||||
$status.application.initialLoading = true;
|
stopping = true;
|
||||||
await post(`/applications/${id}/stop`, {});
|
await post(`/applications/${id}/stop`, {});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return errorNotification(error);
|
return errorNotification(error);
|
||||||
} finally {
|
} finally {
|
||||||
$status.application.initialLoading = false;
|
stopping = false;
|
||||||
await getStatus();
|
await getStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function getStatus() {
|
async function getStatus() {
|
||||||
if ($status.application.loading) return;
|
if ($status.application.loading && stopping) return;
|
||||||
$status.application.loading = true;
|
$status.application.loading = true;
|
||||||
const data = await get(`/applications/${id}/status`);
|
const data = await get(`/applications/${id}/status`);
|
||||||
|
|
||||||
@ -298,7 +298,29 @@
|
|||||||
Application Error
|
Application Error
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
{#if $status.application.initialLoading}
|
{#if stopping}
|
||||||
|
<button class="btn btn-ghost btn-sm gap-2">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-6 w-6 animate-spin duration-500 ease-in-out"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
fill="none"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path d="M9 4.55a8 8 0 0 1 6 14.9m0 -4.45v5h5" />
|
||||||
|
<line x1="5.63" y1="7.16" x2="5.63" y2="7.17" />
|
||||||
|
<line x1="4.06" y1="11" x2="4.06" y2="11.01" />
|
||||||
|
<line x1="4.63" y1="15.1" x2="4.63" y2="15.11" />
|
||||||
|
<line x1="7.16" y1="18.37" x2="7.16" y2="18.38" />
|
||||||
|
<line x1="11" y1="19.94" x2="11" y2="19.95" />
|
||||||
|
</svg>
|
||||||
|
Stopping...
|
||||||
|
</button>
|
||||||
|
{:else if $status.application.initialLoading}
|
||||||
<button class="btn btn-ghost btn-sm gap-2">
|
<button class="btn btn-ghost btn-sm gap-2">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@ -321,7 +343,6 @@
|
|||||||
Loading...
|
Loading...
|
||||||
</button>
|
</button>
|
||||||
{:else if $status.application.overallStatus === 'healthy'}
|
{:else if $status.application.overallStatus === 'healthy'}
|
||||||
|
|
||||||
{#if application.buildPack !== 'compose'}
|
{#if application.buildPack !== 'compose'}
|
||||||
<button
|
<button
|
||||||
on:click={restartApplication}
|
on:click={restartApplication}
|
||||||
@ -370,26 +391,26 @@
|
|||||||
Force Redeploy
|
Force Redeploy
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={stopApplication}
|
on:click={stopApplication}
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!$isDeploymentEnabled}
|
disabled={!$isDeploymentEnabled}
|
||||||
class="btn btn-sm gap-2"
|
class="btn btn-sm gap-2"
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="w-6 h-6 text-error"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke-width="1.5"
|
|
||||||
stroke="currentColor"
|
|
||||||
fill="none"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
>
|
||||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
<svg
|
||||||
<rect x="6" y="5" width="4" height="14" rx="1" />
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
<rect x="14" y="5" width="4" height="14" rx="1" />
|
class="w-6 h-6 text-error"
|
||||||
</svg> Stop
|
viewBox="0 0 24 24"
|
||||||
</button>
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
fill="none"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<rect x="6" y="5" width="4" height="14" rx="1" />
|
||||||
|
<rect x="14" y="5" width="4" height="14" rx="1" />
|
||||||
|
</svg> Stop
|
||||||
|
</button>
|
||||||
{:else if $isDeploymentEnabled && !$page.url.pathname.startsWith(`/applications/${id}/configuration/`)}
|
{:else if $isDeploymentEnabled && !$page.url.pathname.startsWith(`/applications/${id}/configuration/`)}
|
||||||
{#if $status.application.overallStatus === 'degraded'}
|
{#if $status.application.overallStatus === 'degraded'}
|
||||||
<button
|
<button
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
<div class="flex justify-center px-6 pb-8">
|
<div class="flex justify-center px-6 pb-8">
|
||||||
<form on:submit|preventDefault={handleSubmit} class="grid grid-flow-row gap-2 py-4">
|
<form on:submit|preventDefault={handleSubmit} class="grid grid-flow-row gap-2 py-4">
|
||||||
<div class="flex items-start lg:items-center space-x-0 lg:space-x-4 pb-5 flex-col space-y-4 lg:space-y-0">
|
<div class="flex items-start lg:items-center space-x-0 lg:space-x-4 pb-5 flex-col lg:flex-row space-y-4 lg:space-y-0">
|
||||||
<div class="title font-bold">{$t('forms.configuration')}</div>
|
<div class="title font-bold">{$t('forms.configuration')}</div>
|
||||||
<button type="submit" class="btn btn-sm bg-destinations w-full lg:w-fit" class:loading disabled={loading}
|
<button type="submit" class="btn btn-sm bg-destinations w-full lg:w-fit" class:loading disabled={loading}
|
||||||
>{loading
|
>{loading
|
||||||
|
@ -184,14 +184,16 @@
|
|||||||
? 'Verify Remote Docker Engine'
|
? 'Verify Remote Docker Engine'
|
||||||
: 'Check Remote Docker Engine'}</button
|
: 'Check Remote Docker Engine'}</button
|
||||||
>
|
>
|
||||||
|
{#if destination.remoteVerified}
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm"
|
class="btn btn-sm"
|
||||||
class:loading={loading.restart}
|
class:loading={loading.restart}
|
||||||
class:bg-error={!loading.restart}
|
class:bg-error={!loading.restart}
|
||||||
disabled={loading.restart}
|
disabled={loading.restart}
|
||||||
on:click|preventDefault={forceRestartProxy}>{$t('destination.force_restart_proxy')}</button
|
on:click|preventDefault={forceRestartProxy}
|
||||||
>
|
>{$t('destination.force_restart_proxy')}</button
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-2 items-center px-10 ">
|
<div class="grid grid-cols-2 items-center px-10 ">
|
||||||
|
Loading…
Reference in New Issue
Block a user